android传感器数据流程
一. android传感器有哪些?
在frameworks/base/core/java/android/hardware/Sensor.java中定义了android系统所能支持的传感器,例如
public static final int TYPE_ACCELEROMETER = 1;public static final String STRING_TYPE_ACCELEROMETER = "android.sensor.accelerometer";public static final int TYPE_MAGNETIC_FIELD = 2;public static final String STRING_TYPE_MAGNETIC_FIELD = "android.sensor.magnetic_field";public static final int TYPE_ORIENTATION = 3;public static final String STRING_TYPE_ORIENTATION = "android.sensor.orientation";public static final int TYPE_GYROSCOPE = 4;public static final String STRING_TYPE_GYROSCOPE = "android.sensor.gyroscope";public static final int TYPE_LIGHT = 5;public static final String STRING_TYPE_LIGHT = "android.sensor.light";public static final int TYPE_PRESSURE = 6;public static final String STRING_TYPE_PRESSURE = "android.sensor.pressure";public static final int TYPE_TEMPERATURE = 7;public static final String STRING_TYPE_TEMPERATURE = "android.sensor.temperature";public static final int TYPE_PROXIMITY = 8;public static final String STRING_TYPE_PROXIMITY = "android.sensor.proximity";public static final int TYPE_GRAVITY = 9;public static final String STRING_TYPE_GRAVITY = "android.sensor.gravity";public static final int TYPE_LINEAR_ACCELERATION = 10;public static final String STRING_TYPE_LINEAR_ACCELERATION = "android.sensor.linear_acceleration";public static final int TYPE_ROTATION_VECTOR = 11;public static final String STRING_TYPE_ROTATION_VECTOR = "android.sensor.rotation_vector";public static final int TYPE_RELATIVE_HUMIDITY = 12;public static final String STRING_TYPE_RELATIVE_HUMIDITY = "android.sensor.relative_humidity";public static final int TYPE_AMBIENT_TEMPERATURE = 13;public static final String STRING_TYPE_AMBIENT_TEMPERATURE ="android.sensor.ambient_temperature";public static final int TYPE_MAGNETIC_FIELD_UNCALIBRATED = 14;public static final String STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED = "android.sensor.magnetic_field_uncalibrated";public static final int TYPE_GAME_ROTATION_VECTOR = 15;public static final String STRING_TYPE_GAME_ROTATION_VECTOR ="android.sensor.game_rotation_vector";public static final int TYPE_GYROSCOPE_UNCALIBRATED = 16;public static final String STRING_TYPE_GYROSCOPE_UNCALIBRATED = "android.sensor.gyroscope_uncalibrated";public static final int TYPE_SIGNIFICANT_MOTION = 17;public static final String STRING_TYPE_SIGNIFICANT_MOTION ="android.sensor.significant_motion";public static final int TYPE_STEP_DETECTOR = 18;public static final String STRING_TYPE_STEP_DETECTOR = "android.sensor.step_detector";public static final int TYPE_STEP_COUNTER = 19;public static final String STRING_TYPE_STEP_COUNTER = "android.sensor.step_counter";public static final int TYPE_GEOMAGNETIC_ROTATION_VECTOR = 20;public static final String STRING_TYPE_GEOMAGNETIC_ROTATION_VECTOR ="android.sensor.geomagnetic_rotation_vector";public static final int TYPE_HEART_RATE = 21;public static final String STRING_TYPE_HEART_RATE = "android.sensor.heart_rate";public static final int TYPE_TILT_DETECTOR = 22;public static final String SENSOR_STRING_TYPE_TILT_DETECTOR ="android.sensor.tilt_detector";public static final int TYPE_WAKE_GESTURE = 23;public static final String STRING_TYPE_WAKE_GESTURE = "android.sensor.wake_gesture";public static final int TYPE_GLANCE_GESTURE = 24;public static final String STRING_TYPE_GLANCE_GESTURE = "android.sensor.glance_gesture";public static final int TYPE_PICK_UP_GESTURE = 25;public static final String STRING_TYPE_PICK_UP_GESTURE = "android.sensor.pick_up_gesture";public static final int TYPE_WRIST_TILT_GESTURE = 26;public static final String STRING_TYPE_WRIST_TILT_GESTURE = "android.sensor.wrist_tilt_gesture";public static final int TYPE_DEVICE_ORIENTATION = 27;public static final String STRING_TYPE_DEVICE_ORIENTATION = "android.sensor.device_orientation";public static final int TYPE_POSE_6DOF = 28;public static final String STRING_TYPE_POSE_6DOF = "android.sensor.pose_6dof";public static final int TYPE_STATIONARY_DETECT = 29;public static final String STRING_TYPE_STATIONARY_DETECT = "android.sensor.stationary_detect";public static final int TYPE_MOTION_DETECT = 30;public static final String STRING_TYPE_MOTION_DETECT = "android.sensor.motion_detect";public static final int TYPE_HEART_BEAT = 31;public static final String STRING_TYPE_HEART_BEAT = "android.sensor.heart_beat";public static final int TYPE_DYNAMIC_SENSOR_META = 32;public static final String STRING_TYPE_DYNAMIC_SENSOR_META ="android.sensor.dynamic_sensor_meta";
可以看出,android目前支持的传感器有32种,通常所说的加速器、重力感应器、磁场感应器、方向感应器(水平竖直)陀螺仪、距离感应、心率、心跳、光感、温度等传感器都包含在内。这里罗列出来的传感器包含一些虚拟传感器,虚拟传感器通常是一个或多个物理传感器在算法的基础上虚拟化出来的。随着传感器种类的丰富,以后估计会支持更多传感器。
二、android传感器的开发过程
android .java源码经过编译后生成.class文件,.class文件是字节码文件,字节码文件是平台虚拟机能够识别运行的文件,但android的基于linux内核实现,驱动也是运行在内核空间的,应用层通过系统调用来调用内核空间,但linux内核提供的系统调用入口,是java代码不能直接调用的,必须经过C库中的系统调用来实现,也就是说java需要调用C、C++的代码,jni层实现了java调用c c++代码。
基于android平台做传感器的应用程序开发,软件层次自顶向下可以分为四层,java层,jni层,HAL层,驱动层。
我们从最上层说起。创建一个active实例展示传感器的数据。
public class MainActivity extends Activityimplements SensorEventListener
{public void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);// 获取水平仪的主组件show = (MyView) findViewById(R.id.show);// 获取传感器管理服务mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);}@Overridepublic void onResume(){super.onResume();// 为系统的方向传感器注册监听器mSensorManager.registerListener(this,mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),SensorManager.SENSOR_DELAY_GAME);}.......
}
在onCreate函数中,通过getSystemService获取传感器管理器的实例。
那么getSystemService的执行过程是怎样的呢?
onCreate
–>(SensorManager)getSystemService(SENSOR_SERVICE);
–>frameworks\base\core\java\android\app\Activity.java中的getSystemService
—>android\content\ContextThemeWrapper.java中的getSystemService
在ContextThemeWrapper.java中getSystemService的实现如下:
@Overridepublic Object getSystemService(String name) {if (LAYOUT_INFLATER_SERVICE.equals(name)) {if (mInflater == null) {mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);}return mInflater;}return getBaseContext().getSystemService(name);}
发现调用的是android\content\Context.java中的getSystemService。进入Context.java查看源码
//file android\content\Context.javapublic abstract @Nullable Object getSystemService(@ServiceName @NonNull String name);public final @Nullable <T> T getSystemService(@NonNull Class<T> serviceClass) {// Because subclasses may override getSystemService(String) we cannot// perform a lookup by class alone. We must first map the class to its// service name then invoke the string-based method.String serviceName = getSystemServiceName(serviceClass);return serviceName != null ? (T)getSystemService(serviceName) : null;}public abstract @Nullable String getSystemServiceName(@NonNull Class<?> serviceClass);
先通过getSystemServiceName获取服务名字,然后调用了泛类参数serviceClass的getSystemService返回结果。
那么抽象函数getSystemServiceName和serviceClass分别在哪里实现的呢?
先列出相关类的关系:
public class MainActivity extends Activity
public class Activity extends ContextThemeWrapper
public class ContextThemeWrapper extends ContextWrapper
public class ContextWrapper extends Context
public abstract class Context
不妨先从这几个类当中找一下getSystemServiceName函数的实现。
在content\ContextWrapper.java中找到了getSystemServiceName实现。
//content\ContextWrapper.java
public class ContextWrapper extends Context{Context mBase;public ContextWrapper(Context base) {mBase = base;}protected void attachBaseContext(Context base) {if (mBase != null) {throw new IllegalStateException("Base context already set");}mBase = base;}@Overridepublic String getSystemServiceName(Class<?> serviceClass) {return mBase.getSystemServiceName(serviceClass);}@Overridepublic Object getSystemService(String name) {return mBase.getSystemService(name);}
}
可以看出在onCreate函数中调用的getSystemService最终其实还是context中的getSystemService,依然没有找到getSystemService的具体实现。
在网上查了资料说是android/app/ContextImpl.java中实现Context.java中的所有方法,那么刚才的getSystemService就在ContextImpl.java中实现了。但看了代码没有找到import ContextImpl.java的地方,这说明有可能是在跟ContextImpl同包的文件中引用了。
这可以从安卓应用程序的入口说起(参考
https://blog.csdn.net/shifuhetudi/article/details/52089562
)
在ActivityThread中,通过传入主线程对象创建了一个系统的ContextImpl,刚才的getSystemService正是在ContextImpl.java中的getSystemService。
@Overridepublic Object getSystemService(String name) {return SystemServiceRegistry.getSystemService(this, name);}
// frameworks\base\core\java\android\app\SystemServiceRegistry.java// This information is never changed once static initialization has completed.private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =new HashMap<Class<?>, String>();private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =new HashMap<String, ServiceFetcher<?>>();private static int sServiceCacheSize;public static Object getSystemService(ContextImpl ctx, String name) {ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);return fetcher != null ? fetcher.getService(ctx) : null;}private static <T> void registerService(String serviceName, Class<T> serviceClass,ServiceFetcher<T> serviceFetcher) {SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);}static{.......registerService(Context.SENSOR_SERVICE, SensorManager.class,new CachedServiceFetcher<SensorManager>() {@Overridepublic SensorManager createService(ContextImpl ctx) {return new SystemSensorManager(ctx.getOuterContext(),ctx.mMainThread.getHandler().getLooper());}});}static abstract class StaticServiceFetcher<T> implements ServiceFetcher<T> {private T mCachedInstance;@Overridepublic final T getService(ContextImpl unused) {synchronized (StaticServiceFetcher.this) {if (mCachedInstance == null) {// 如果service不存在,//则调用createService就是我们上面在registerservice时重载的createService方法,里面就是new 了一个SystemSensorManager mCachedInstance = createService();}return mCachedInstance;}}public abstract T createService();}
在SystemServiceRegistry.java的内部类StaticServiceFetcher中实现了getService方法,并且声明了一个createService抽象函数,所以继承SystemServiceRegistry的子类需要实现createService的方法。
而在registerService SENSOR_SERVICE的时候,实现了一个createService,其实就是调用了new SystemSensorManager,而SystemSensorManager的构造函数里面就调用了JNI的函数。
从网上找到一张调用关系图,如下
那么问题来了,SystemSensorManager是怎样直接就能调用frameworks\base\core\jni\android_hardware_SensorManager.cpp里面的nativeClassInit呢?
这跟vm映射原理、jni环境的导入有关系。
//frameworks\base\core\jni\android_hardware_SensorManager.cpp
static const JNINativeMethod gSystemSensorManagerMethods[] = {{"nativeClassInit","()V",(void*)nativeClassInit },{"nativeCreate","(Ljava/lang/String;)J",(void*)nativeCreate },{"nativeGetSensorAtIndex","(JLandroid/hardware/Sensor;I)Z",(void*)nativeGetSensorAtIndex },{"nativeGetDynamicSensors","(JLjava/util/List;)V",(void*)nativeGetDynamicSensors },{"nativeIsDataInjectionEnabled","(J)Z",(void*)nativeIsDataInjectionEnabled},
};int register_android_hardware_SensorManager(JNIEnv *env)
{RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager",gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods));RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager$BaseEventQueue",gBaseEventQueueMethods, NELEM(gBaseEventQueueMethods));gBaseEventQueueClassInfo.clazz = FindClassOrDie(env,"android/hardware/SystemSensorManager$BaseEventQueue");gBaseEventQueueClassInfo.dispatchSensorEvent = GetMethodIDOrDie(env,gBaseEventQueueClassInfo.clazz, "dispatchSensorEvent", "(I[FIJ)V");gBaseEventQueueClassInfo.dispatchFlushCompleteEvent = GetMethodIDOrDie(env,gBaseEventQueueClassInfo.clazz, "dispatchFlushCompleteEvent", "(I)V");gBaseEventQueueClassInfo.dispatchAdditionalInfoEvent = GetMethodIDOrDie(env,gBaseEventQueueClassInfo.clazz, "dispatchAdditionalInfoEvent", "(III[F[I)V");return 0;
}
//register_android_hardware_SensorManager在什么时候执行呢?
//core/jni/AndroidRuntime.cpp
core/jni/AndroidRuntime.cpp:91:extern int register_android_hardware_SensorManager(JNIEnv *env);
core/jni/AndroidRuntime.cpp:1373: REG_JNI(register_android_hardware_SensorManager),
1265 static const RegJNIRec gRegJNI[] = {
1266 REG_JNI(register_android_util_SeempLog),
1267 REG_JNI(register_com_android_internal_os_RuntimeInit),
1268 REG_JNI(register_android_os_SystemClock),
1269 REG_JNI(register_android_util_EventLog),
1270 REG_JNI(register_android_util_Log),
1271 REG_JNI(register_android_util_MemoryIntArray),
1272 REG_JNI(register_android_util_PathParser),
1273 REG_JNI(register_android_app_admin_SecurityLog),
1274 REG_JNI(register_android_content_AssetManager),
1275 REG_JNI(register_android_content_StringBlock),
1276 REG_JNI(register_android_content_XmlBlock),
1277 REG_JNI(register_android_text_AndroidCharacter),
1278 REG_JNI(register_android_text_StaticLayout),
1279 REG_JNI(register_android_text_AndroidBidi),
1280 REG_JNI(register_android_view_InputDevice),
1281 REG_JNI(register_android_view_KeyCharacterMap),
1282 REG_JNI(register_android_os_Process),
1283 REG_JNI(register_android_os_SystemProperties),
1284 REG_JNI(register_android_os_Binder),
.......
1372 REG_JNI(register_android_hardware_Radio),
1373 REG_JNI(register_android_hardware_SensorManager),
1374 REG_JNI(register_android_hardware_SerialPort),
1375 REG_JNI(register_android_hardware_SoundTrigger),
1376 REG_JNI(register_android_hardware_UsbDevice),
1377 REG_JNI(register_android_hardware_UsbDeviceConnection),
1378 REG_JNI(register_android_hardware_UsbRequest),
}
1420 * Register android native functions with the VM.
1421 */
1422 /*static*/ int AndroidRuntime::startReg(JNIEnv* env)
1423 {
1424 ATRACE_NAME("RegisterAndroidNatives");
1425 /*
1426 * This hook causes all future threads created in this process to be
1427 * attached to the JavaVM. (This needs to go away in favor of JNI
1428 * Attach calls.)
1429 */
1430 androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
1431
1432 ALOGV("--- registering native functions ---\n");
1433
1434 /*
1435 * Every "register" function calls one or more things that return
1436 * a local reference (e.g. FindClass). Because we haven't really
1437 * started the VM yet, they're all getting stored in the base frame
1438 * and never released. Use Push/Pop to manage the storage.
1439 */
1440 env->PushLocalFrame(200);
1441
1442 if (register_jni_procs(**gRegJNI**, NELEM(gRegJNI), env) < 0) {
1443 env->PopLocalFrame(NULL);
1444 return -1;
1445 }
1446 env->PopLocalFrame(NULL);
1447
1448 //createJavaThread("fubar", quickTest, (void*) "hello");
1449
1450 return 0;
1451 }
上面的starg函数,由app:main,
app_main.cpp的main()方法最终调用了AndroidRuntime的start()方法.start函数完成了下面的功能。1. jni_invocation.Init()方法初始化jni接口2. startVm()方法创建虚拟机3. startReg()方法注册Android方法4. CallStaticVoidMethod()方法打开ZygoteInit类的main方法。完成从c/c++到java代码。// 在startReg中引入了native方法。
看了上面的分析后,SystemSensorManager调用了nativeCreate 和 nativeGetSensorAtIndex,为java层填充了各个sensor的实例。
现在捋一下getSystemService调用过程。
Oncreate
—>mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
—>Context.java getSystemService
—>COntextImpl.java getSystemService,这里得到的是在register SENSOR_SERVICE的时候已经SystemSensorManager
而register SENSOR_SERVICE的过程是:
SystemSensorManager.java—>android_hardware_SensorManager.cpp,填充了各个sensor的实例。
拿到了SystemSensorManager实例后,就可以使用mSensorManager.registerListener监听指定类型的sensor。
public boolean registerListener(SensorEventListener listener, Sensor sensor,int samplingPeriodUs) {return registerListener(listener, sensor, samplingPeriodUs, null);}
android传感器数据流程相关推荐
- android gps时间格式,android gps 数据传输流程
Android GPS数据流程分析 概述: 该文档将介绍android GPS数据流程分析,在debug的时候可以做为数据流的捕捉的参考. ============================== ...
- 新大陆物联网-Android实现网关功能-连接云平台并上传传感器数据-获取执行器指令并执行-Android网关开发-通信-数据上传云平台-JAVA原理讲解-免费云平台使用-竞赛2022国赛真题
目录 一.任务要求 二.开发环境 三.网关上线 四.数据上传与命令下发 五.JSON命令解析思路 六.总结 一.任务要求 我们将要实现的效果是:Android开发平板与Lora板进行有线串口通信,解析 ...
- Pixhawk的传感器数据(陀螺、加计等)流程
一.总体流程 先由驱动层drive,再到中间层sensor,再到应用层ekf2,最后发布数据给其他应用.控制系统最重要的是带宽,位置环的带宽,到速度环的带宽,再到传感器的更新率,所以,做控制,看程序的 ...
- android 获取加速度传感器值,Android开发获取传感器数据的方法示例【加速度传感器,磁场传感器,光线传感器,方向传感器】...
本文实例讲述了Android开发获取传感器数据的方法.分享给大家供大家参考,具体如下: package mobile.android.sensor; import java.util.List; im ...
- Android手机HC-05蓝牙连接Arduino nano获取DHT-11温湿度传感器数据
如果您觉得本文对您有用,希望您点赞,收藏并且把它分享出去,不明白的可以在评论区留言,我会一一解答,感谢您的支持!! 目标 Android手机HC-05蓝牙连接Arduino nano获取DHT-11温 ...
- android开发中磁场传感器,Android开发获取传感器数据的方法示例【加速度传感器,磁场传感器,光线传感器,方向传感器】...
本文实例讲述了Android开发获取传感器数据的方法.分享给大家供大家参考,具体如下: package mobile.android.sensor; import java.util.List; im ...
- 使用 Qt for Android 获取并利用手机传感器数据(上篇)开发环境省心搭建
现代手机拥有许多传感器,包括地磁.姿态.GPS.光照.温度.气压.摄像.声音.电磁等,完全就是一个高度集成的科学仪器.不夸张的说,一部手机加上一个外围的计算机和控制系统,做一个功能较强的自主移动机器人 ...
- 使用 Qt for Android 获取并利用手机传感器数据(下篇)使用C++实现功能
在上一篇,我们搭建了开发环境.本篇,使用C++代码真正实现功能.我们使用UDP协议从手机上指定发送的目的地.端口.效果如下图,完整工程参考https://gitcode.net/coloreagles ...
- Android开发:按一定频率同时获取多个传感器数据
最近在做室内定位相关研究,希望通过手机传感器数据判断人的姿态和手机位置.之前很多研究只用到了加速度数据,但是判别的准确度偏低.本次我们的研究准备将加速度传感器.角速度传感器.方位传感器.压力传感器等数 ...
最新文章
- Linux_查看CPU信息、机器型号等硬件信息
- 网易云信助力长沙银行打造远程视频银行 | 字母点评数字化先锋案例
- python模块安装路径
- 阿里媒体转码公共参数_Xuggler教程:转码和媒体修改
- GenePix Pro 3.0
- ‘packaging‘ with value ‘jar‘ is invalid. Aggregator projects require ‘pom‘ as packaging.
- allwinner h6 armv8 SylixOS 启动分析
- 微型计算机的分类通常以什么来划分,微机的分类通常以微处理器的什么来划分...
- Python 二次开发 AutoCAD 简介
- fastboot模式下无法找到设备,不能使用fastboot命令,需要安装驱动
- vue项目动态域名设置方法
- (附源码)计算机毕业设计SSM基于框架的旅游订票系统
- vue-router 采坑记录
- MATLAB快速获取二维图像/矩阵最大值和位置
- Centos使用yum报错---网络问题
- python中string什么意思_python字符串(string)方法整理
- Leetcode 738. 单调递增的数字
- java字符串去重_java字符串去重方法详解,字符串如何去重?
- 聊天机器人突然火了 Line宣布也将开发挑战FB们
- vue-echarts画深度图
热门文章
- Linux 操作系统的安装
- 数据库作业:SQL练习2 - INDEX / INSERT / SELECT
- Vue SPA应用微信开发踩坑记录
- Veritas调研显示:全球企业普遍担心由于不符合新欧盟数据条例导致业务受损
- qrCode生成二维码图片
- 【论文笔记】《SketchMate: Deep Hashing for Million-Scale Human Sketch Retrieval》
- 报错: Called “net usershare info“ but it failed
- mysql5.1 优化_7. 优化 - [ MySQL 5.1参考手册 ] - 在线原生手册 - php中文网
- 老男孩Python全栈9期视频完整版
- 新上线的材料计算超算云平台Mcloud V2.0版本推出全新功能——web端工作流拖拽提交作业+便捷web端建模