本节主要分析的是java层次相关的软件内容

Application开发

谷歌开发者网站 sensors 中提供了AOSP提供的sensor相关的api介绍及demo;

可以参考下相关资源:

  • 传感器
  • 动态传感器
  • 位置传感器
  • 环境传感器
  • Accelerometer Play
  • API 演示 (OS - RotationVectorDemo)

App demo 实现

public class MainActivity extends AppCompatActivity implements SensorEventListener {private SensorManager mSensorManager;private Sensor mSensorAcc, mSensorMag;private TextView tvAcc, tvMag;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Toolbar toolbar = findViewById(R.id.toolbar);setSupportActionBar(toolbar);tvAcc = findViewById(R.id.tvAcc);tvMag = findViewById(R.id.tvMag);mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);//!< 通过getSystemService获得SensorManager实例对象 >! NoteBy: yujixuanmSensorAcc = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);//!< 通过SensorManager 获取sensor对象 >! NoteBy: yujixuan}@Overridepublic final void onSensorChanged(SensorEvent event) {float x = event.values[0];float y = event.values[1];float z = event.values[2];if(event.sensor == mSensorAcc)tvAcc.setText("x:" + x + "\ny:" + y + "\nz:" + z);}@Overrideprotected void onResume() {super.onResume();mSensorManager.registerListener(this, mSensorAcc, SensorManager.SENSOR_DELAY_NORMAL);}@Overrideprotected void onPause() {super.onPause();mSensorManager.unregisterListener(this);}
}

实现的步骤:

  1. 通过调用通过getSystemService获得传感器服务,实现返回的是封装了SensorService的SensorManager对象
  2. 通过SensorManager 来获得指定类型的传感器对象,用来获得传感器的数据
  3. 通过SensorManager.registerListener注册SensorEventListener监听器,监听传感器
  4. 实现对sensor上报数据内容的具体操作

运行demo

以下是在Android Studio中实际demo

SensorManager

通过上面简单的app demo可知,主要过程均是通过SensorManager来完成;

改SensorManager是通过 getSystemService获取系统name 为“sensor” service得到;

/*** Use with {@link #getSystemService(String)} to retrieve a {@link* android.hardware.SensorManager} for accessing sensors.** @see #getSystemService(String)* @see android.hardware.SensorManager*/
public static final String SENSOR_SERVICE = "sensor";

Sensor服务用户程序不能直接访问, android.hardware.SensorManager 是真正用来在java程序中操作sensor的类,它是SensorService提供服务接口的封装。

因为 Manager是应用程序直接面对的接口, Manager里维护对应的Service,应用程序不能直接访问Service;

Service是服务,被所有的应用共享的服务,并非属于某一个特定的进程,也即Sensor application与SensorService不在同一个进程内,App需要使用Sensor

service就需要进程间通信,这显然不利于很高效率的开发程序,为此由manager类操作,隐藏共享操作,把细节实现隐藏封装,app应用程序只需要通过访问被暴

露出来的api接口,所以应用中与之直接交互的是SensorManager;

SensorManager提供了各种方法来访问和列出传感器,注册和取消注册传感器事件监听器,它还提供了几个传感器常量,用于报

告传感器精确度,设置数据采集频率和校准传感器;下面是这个类的定义:

public abstract class SensorManager protected static final String TAG = "SensorManager";public static final int RAW_DATA_Z = 5;/** Standard gravity (g) on Earth. This value is equivalent to 1G */public static final float STANDARD_GRAVITY = 9.80665f;
......public SensorManager() {}protected abstract List<Sensor> getFullSensorList();protected abstract List<Sensor> getFullDynamicSensorList();@Deprecatedpublic int getSensors() {return getLegacySensorManager().getSensors();}public List<Sensor> getSensorList(int type) {// cache the returned lists the first timeList<Sensor> list;final List<Sensor> fullList = getFullSensorList();synchronized (mSensorListByType) {list = mSensorListByType.get(type);if (list == null) {if (type == Sensor.TYPE_ALL) {list = fullList;} else {list = new ArrayList<Sensor>();for (Sensor i : fullList) {if (i.getType() == type)list.add(i);}}list = Collections.unmodifiableList(list);mSensorListByType.append(type, list);}}return list;}@Deprecatedpublic boolean registerListener(SensorListener listener, int sensors) {return registerListener(listener, sensors, SENSOR_DELAY_NORMAL);}public boolean registerListener(SensorEventListener listener, Sensor sensor,int samplingPeriodUs, Handler handler) {int delay = getDelay(samplingPeriodUs);return registerListenerImpl(listener, sensor, delay, handler, 0, 0);}public void unregisterListener(SensorEventListener listener, Sensor sensor) {if (listener == null || sensor == null) {return;}unregisterListenerImpl(listener, sensor);}public boolean flush(SensorEventListener listener) {return flushImpl(listener);}
.......
}

通过上面的内容可以看出SensorManager是个抽象类,真正完成管理控制sensor的是它的子类SystemSensorManager;

SystemSensorManager继承了它 做具体的实现;

SystemSensorManager.java extends SensorManagerpublic class SystemSensorManager extends SensorManager {//TODO: disable extra logging before releaseprivate static boolean DEBUG_DYNAMIC_SENSOR = true;private static native void nativeClassInit();private static native long nativeCreate(String opPackageName);private static native boolean nativeGetSensorAtIndex(long nativeInstance,Sensor sensor, int index);private static native void nativeGetDynamicSensors(long nativeInstance, List<Sensor> list);private static native boolean nativeIsDataInjectionEnabled(long nativeInstance);private static final Object sLock = new Object();@GuardedBy("sLock")private static boolean sNativeClassInited = false;@GuardedBy("sLock")private static InjectEventQueue sInjectEventQueue = null;private final ArrayList<Sensor> mFullSensorsList = new ArrayList<>();private List<Sensor> mFullDynamicSensorsList = new ArrayList<>();private boolean mDynamicSensorListDirty = true;private final HashMap<Integer, Sensor> mHandleToSensor = new HashMap<>();
......public SystemSensorManager(Context context, Looper mainLooper) {synchronized(sLock) {if (!sNativeClassInited) {sNativeClassInited = true;nativeClassInit();}}mMainLooper = mainLooper;mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;mContext = context;mNativeInstance = nativeCreate(context.getOpPackageName());// initialize the sensor listfor (int index = 0;;++index) {Sensor sensor = new Sensor();if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;mFullSensorsList.add(sensor);mHandleToSensor.put(sensor.getHandle(), sensor);}}
......@Overrideprotected List<Sensor> getFullSensorList() {return mFullSensorsList;
......private static abstract class BaseEventQueue {private static native long nativeInitBaseEventQueue(long nativeManager,WeakReference<BaseEventQueue> eventQWeak, MessageQueue msgQ,String packageName, int mode, String opPackageName);private static native int nativeEnableSensor(long eventQ, int handle, int rateUs,int maxBatchReportLatencyUs);private static native int nativeDisableSensor(long eventQ, int handle);private static native void nativeDestroySensorEventQueue(long eventQ);private static native int nativeFlushSensor(long eventQ);private static native int nativeInjectSensorData(long eventQ, int handle,}
......}

从这个类中可以本地的native方法,如:

nativeClassInit();
nativeCreate(String opPackageName);
nativeGetSensorAtIndex(long nativeInstance,Sensor sensor, int index);
nativeGetDynamicSensors(long nativeInstance, List<Sensor> list);
nativeIsDataInjectionEnabled(long nativeInstance);

通过load到的JNI访问到libc中的native方法,有关jni 和c++ 本地方法实现后面博客介绍;

除了对本地native方法的调用,SystemSensorManager 还在其构造函数中 初始化了对应的sensor list;

        for (int index = 0;;++index) {Sensor sensor = new Sensor();if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;mFullSensorsList.add(sensor);mHandleToSensor.put(sensor.getHandle(), sensor);}

Sensor对象

从app的demo代码中可以看出,一个存在的sensor是由一个Sensor类的对象来标识的,它获取自Sensor Manager,通过给定的参数,获取一个实例sensor对象;该类提供了各种方法来确定传感器的特性。

mSensorAcc = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
public Sensor getDefaultSensor(int type) {// TODO: need to be smarter, for now, just return the 1st sensorList<Sensor> l = getSensorList(type);boolean wakeUpSensor = false;// For the following sensor types, return a wake-up sensor. These types are by default// defined as wake-up sensors. For the rest of the SDK defined sensor types return a// non_wake-up version.if (type == Sensor.TYPE_PROXIMITY || type == Sensor.TYPE_SIGNIFICANT_MOTION ||type == Sensor.TYPE_TILT_DETECTOR || type == Sensor.TYPE_WAKE_GESTURE ||type == Sensor.TYPE_GLANCE_GESTURE || type == Sensor.TYPE_PICK_UP_GESTURE ||type == Sensor.TYPE_WRIST_TILT_GESTURE) {wakeUpSensor = true;}for (Sensor sensor : l) {if (sensor.isWakeUpSensor() == wakeUpSensor) return sensor;}return null;
}

Sensor类的内容如下:

public final class Sensor {mNamemVendormVersionmHandlemTypemMaxRangemResolutionmPowermMinDelaymFifoReservedEventCountmFifoMaxEventCountmStringTypemRequiredPermissionmMaxDelaymFlagsmld
// funcSensorgetNamegetVendorgetTypegetVersiongetMaximumRangegetResolutiongetPowergetMinDelaygetFifoReservedEventCountgetFifoMaxEventCountgetStringTypegetUuidgetldgetRequiredPermissiongetHandlegetMaxDelayisWakeUpSensorisDynamicSensorisAdditionallnfoSupportedisDatalnjectionSupportedsetRangetoStringsetTypesetUuid
}

Sensor Event 处理

SensorEventListener

回到app demo中,可以看出,sensor数据的处理是override了onSensorChanged方法,它在有sensor数据上报时被回调,详细的回调过程后面的内容会做分析;暂时只关注demo中的代码实现;

通过activity的定义可知,onSensorChanged方法是来自接口SensorEventListener;

接口类interface SensorEventListener (方法都是public abstract, 变量都是public static final)

用于接收新的sensor 数据上报时回调其中的抽象方法;

code:frameworks\base\core\java\android\hardware\SensorEvent.java
public interface SensorEventListener {public void onSensorChanged(SensorEvent event); //sensor数据变化public void onAccuracyChanged(Sensor sensor, int accuracy); //精度变化
}

它处理的参数类型是SensorEvent类对象;这个类的对象表示一个SensorEvent事件,并保存诸如传感器类型、时间戳、精度等信息,还有传感器的数据。

values float数组里保存了app需要用到的数据信息;按照固定的格式去读取需要的参数即可; 具体参考android API介绍,拿到event之后,对应固定的格式,拆解出的value即是我们需要的sensor数据;

public class SensorEvent {public final float[] values;
public Sensor sensor;
public int accuracy;
public long timestamp;
SensorEvent(int valueSize) {values = new float[valueSize];}
}

registerListener

实现一个sensor监听,是先通过SensorManager.registerListener注册SensorEventListener监听器,监听sensor,注册监听器的方法实现同样是有SensorManager对象来管理,appdemo中使用获取到的mSensorManager,以及设置指定类型获取的sensor对象 acc msensor来注册监听;

mSensorManager.registerListener(this, mSensorAcc, SensorManager.SENSOR_DELAY_NORMAL);

以下是registerListener在SystemSensorManager类中的定义:

SystemSensorManager::registerListener
protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {//......// listener 是activity// - one Looper per SensorEventListener// - one Looper per SensorEventQueue//   将SensorEventListener映射到一个SensorEventQueuesynchronized (mSensorListeners) {SensorEventQueue queue = mSensorListeners.get(listener);if (queue == null) {Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;final String fullClassName = listener.getClass().getEnclosingClass() != null ?listener.getClass().getEnclosingClass().getName() :listener.getClass().getName();queue = new SensorEventQueue(listener, looper, this, fullClassName);if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs)) {queue.dispose();return false;}mSensorListeners.put(listener, queue);return true;} else {return queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs);}}//......
}

将SensorEventListener映射到一个SensorEventQueue,如果SensorEventQueue已经存在,将该sensor(mSensorAcc)添加到queue中去,如果不存在,则创建SensorEventQueue;以下是SensorEventQueue 队列的实现:

SensorEventQueue

prj\frameworks\base\core\java\android\hardware\SystemSensorManager.java
static final class SensorEventQueue extends BaseEventQueue {private final SensorEventListener mListener;private final SparseArray<SensorEvent> mSensorsEvents = new SparseArray<SensorEvent>();public SensorEventQueue(SensorEventListener listener, Looper looper,SystemSensorManager manager, String packageName) {super(looper, manager, OPERATING_MODE_NORMAL, packageName);mListener = listener;}@Overridepublic void addSensorEvent(Sensor sensor) {SensorEvent t = new SensorEvent(Sensor.getMaxLengthValuesArray(sensor,mManager.mTargetSdkLevel));synchronized (mSensorsEvents) {mSensorsEvents.put(sensor.getHandle(), t);}}
}// Called from native code.protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,long timestamp) {final Sensor sensor = mManager.mHandleToSensor.get(handle);if (sensor == null) {// sensor disconnectedreturn;}SensorEvent t = null;synchronized (mSensorsEvents) {t = mSensorsEvents.get(handle);}// Copy from the values array.System.arraycopy(values, 0, t.values, 0, t.values.length);t.timestamp = timestamp;t.accuracy = inAccuracy;t.sensor = sensor;// call onAccuracyChanged() only if the value changesfinal int accuracy = mSensorAccuracies.get(handle);if ((t.accuracy >= 0) && (accuracy != t.accuracy)) {mSensorAccuracies.put(handle, t.accuracy);mListener.onAccuracyChanged(t.sensor, t.accuracy);}mListener.onSensorChanged(t);}

BaseEventQueue

它继承自BaseBaseEventQueue; 以下是 BaseEventQueue的定义:

prj\frameworks\base\core\java\android\hardware\SystemSensorManager.java
private static abstract class BaseEventQueue {private static native long nativeInitBaseEventQueue(long nativeManager,WeakReference<BaseEventQueue> eventQWeak, MessageQueue msgQ,String packageName, int mode, String opPackageName);private static native int nativeEnableSensor(long eventQ, int handle, int rateUs,int maxBatchReportLatencyUs);private static native int nativeDisableSensor(long eventQ, int handle);private static native void nativeDestroySensorEventQueue(long eventQ);private static native int nativeFlushSensor(long eventQ);private static native int nativeInjectSensorData(long eventQ, int handle,float[] values,int accuracy, long timestamp);private long nSensorEventQueue;private final SparseBooleanArray mActiveSensors = new SparseBooleanArray();protected final SparseIntArray mSensorAccuracies = new SparseIntArray();private final CloseGuard mCloseGuard = CloseGuard.get();protected final SystemSensorManager mManager;protected static final int OPERATING_MODE_NORMAL = 0;protected static final int OPERATING_MODE_DATA_INJECTION = 1;BaseEventQueue(Looper looper, SystemSensorManager manager, int mode, String packageName) {if (packageName == null) packageName = "";nSensorEventQueue = nativeInitBaseEventQueue(manager.mNativeInstance,new WeakReference<>(this), looper.getQueue(),packageName, mode, manager.mContext.getOpPackageName());mCloseGuard.open("dispose");mManager = manager;}public boolean addSensor(Sensor sensor, int delayUs, int maxBatchReportLatencyUs) {// Check if already present.int handle = sensor.getHandle();if (mActiveSensors.get(handle)) return false;// Get ready to receive events before calling enable.mActiveSensors.put(handle, true);addSensorEvent(sensor);if (enableSensor(sensor, delayUs, maxBatchReportLatencyUs) != 0) {// Try continuous mode if batching fails.if (maxBatchReportLatencyUs == 0 ||maxBatchReportLatencyUs > 0 && enableSensor(sensor, delayUs, 0) != 0) {removeSensor(sensor, false);return false;}}return true;}@Overridepublic void addSensorEvent(Sensor sensor) {SensorEvent t = new SensorEvent(Sensor.getMaxLengthValuesArray(sensor,mManager.mTargetSdkLevel));synchronized (mSensorsEvents) {mSensorsEvents.put(sensor.getHandle(), t);}}private int enableSensor(Sensor sensor, int rateUs, int maxBatchReportLatencyUs) {if (nSensorEventQueue == 0) throw new NullPointerException();if (sensor == null) throw new NullPointerException();return nativeEnableSensor(nSensorEventQueue, sensor.getHandle(), rateUs,maxBatchReportLatencyUs);}

SensorList获取

前面SensorManager构造函数中,有提过获取sensor list的过程,它在java代码中的实现如下;

public List<Sensor> getSensorList(int type) {// cache the returned lists the first timeList<Sensor> list;final List<Sensor> fullList = getFullSensorList();synchronized (mSensorListByType) {list = mSensorListByType.get(type);if (list == null) {if (type == Sensor.TYPE_ALL) {list = fullList;} else {list = new ArrayList<Sensor>();for (Sensor i : fullList) {if (i.getType() == type)list.add(i);}}list = Collections.unmodifiableList(list);mSensorListByType.append(type, list);}}return list;}
protected List<Sensor> getFullSensorList() {return mFullSensorsList;
}

实际上是反回了mFullSensorsList 列表,实际的初始化过程是子类SystemSensorManager的构造过程中实现的,如下;

// initialize the sensor list
for (int index = 0;;++index) {Sensor sensor = new Sensor();if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;mFullSensorsList.add(sensor);mHandleToSensor.put(sensor.getHandle(), sensor);
}

可以看到 每一个sensor都是通过new Sensor对象,再调用本地native方法nativeGetSensorAtIndex去做实例;

本节主要分析的是java层次相关的软件内容,nativeGetSensorAtIndex通过jni访问到C++中的sensor manager,在后续的博客汇总介绍;

Android Senor Framework (二) Application相关推荐

  1. Android Senor Framework (五) SensorManager

    SensorManager 通过前面的博客介绍可知在Java application中, 由SystemSensorManage对象管理每一个sensor: 在msm8909平台的HAL sensor ...

  2. Android Senor Framework (四)SensorService加载

    onFirstRef 前个内容介绍了 SystemServer启动SensorService的过程,同时描述了 SensorService有集成它的类间接父类RefBase,SesnorService ...

  3. Android Senor Framework (三)SensorService启动

    SystemServer 启动SensorService Zygote启动之后,调用SystemServer的main方法(调用run方法)启动系统服务: 代码路径: ./frameworks/bas ...

  4. Android 进阶——Framework 核心之Android Storage Access Framework(SAF)存储访问框架机制详解(二)

    文章大纲 引言 一.DirectFragment 1.当选中DirectoryFragment中RecyclerView的Item时 2.选中DirectoryFragment中RecyclerVie ...

  5. Android Automotive (二)系统架构

    Android Automotive (二)系统架构 前面简单介绍了一下Android Automotive 的架构,具体Android Automotive 在系统的每个层,都做了哪些东西,这里总结 ...

  6. Android开发者指南(4) —— Application Fundamentals

    前言 本章内容为开发者指南(Dev Guide)/Framework Topics/Application Fundamentals,版本为Android2.3 r1,翻译转载并整理自译言:" ...

  7. 如何调试Android Native Framework

    原文: https://zhuanlan.zhihu.com/p/24867284 如何调试Android Native Framework weishu 7 个月前 半年前写了一篇文章,介绍 如何调 ...

  8. 【Android 应用开发】 Application 使用分析

    博客地址 : http://blog.csdn.net/shulianghan/article/details/40737419 代码下载 : Android 应用 Application 经典用法; ...

  9. dagger android 学习(二):AndroidInjector的使用

    本系列博客主要用于自己学习积累,顺便帮助新手入门,如有问题,多多包涵.更详细的一些使用可以看看其他更加详细的博客. dagger android 学习(一):dagger基础使用 dagger and ...

最新文章

  1. 法国呼叫服务公司Aircall获得800万美元融资
  2. 解决IDEA使用lombok注解无效,@Data不生效问题
  3. VTK:PolyData之OrientedBoundingCylinder
  4. 看动画学算法之:排序-归并排序
  5. 单步调试学习NgRx createSelector 工具函数的使用方式
  6. 我的asp.net学习心得
  7. 前端学习(1319):node.js异步编程
  8. python 树结构 sqlalchemy_如何从SQLalchemy mod创建json树结构
  9. rls数据预测_SQL Server数据安全功能RLS(行级安全性)和GDPR
  10. 计算机软件著作权登记怎么填写,计算机软件著作权登记申请表填写说明
  11. Google的Guava开发库快速快速入门
  12. Java 8 你需要掌握的新特性
  13. nginx部署前端代码
  14. Pycharm 通过按住 ctrl +滑动鼠标滚轮实现代码窗口字体大小调整
  15. 计算机化学博士点,2017年新增博士硕士授予单位公布!各高校博士、硕士学位授权点建设的总体情况如何?...
  16. 手机安全卫士------手机防盗页面之sim卡绑定读取联系人
  17. 【GTASA】路人PED替换语音教程
  18. Web前端js实现tif文件浏览(含多页tif)
  19. 文化IP能量有多大,舞台就有多大
  20. Graphviz安装向导及入门指南

热门文章

  1. 浏览器(IE 下载设置不默认迅雷)
  2. 傻妞对接青龙,对接QQ、TG、微信。一键、DOCKER安装----JD挂机一体化平台搭建之篇三【2022.11.29】
  3. 第四篇、vue组件生命周期 beforeDestroy()和destroyed()
  4. 软件太臃肿了,如何解决?
  5. 命令行删除目录下指定日期前文件
  6. ip route 命令介绍
  7. 如何在Vim中移动到行尾?
  8. Winrar阻止弹窗分析(鼓捣版)
  9. 广西南宁机器人比赛_南宁举行机器人、创客竞赛,2000多名中小学生赛场大比拼...
  10. 站在工业互联时代,看“新晋独角兽”思谋科技的“远方”与“现实”