`

android系统学习笔记十二

阅读更多

Android的传感器系统

 

传感器的种类

传感器名称

Java中的名称

本地接口名称

数值

加速度

TYPE_ACCELEROMETER

SENSOR_TYPE_ACCELEROMETER

1

磁场

TYPE_MAGNETIC_FIELD

SENSOR_TYPE_MAGNETIC_FIELD

2

方向

TYPE_ORIENTATION

SENSOR_TYPE_ORIENTATION

3

陀螺仪

TYPE_GYROSCOPE

SENSOR_TTYPE_GYROSCOPE

4

光线(亮度)

TYPE_LIGHT

SENSOR_TTYPE_LIGHT

5

压力

TYPE_PRESSURE

SENSOR_TTYPE_PRESSURE

6

温度

TYPE_TEMPERATURE

SENSOR_TTYPE_TEMPERATURE

7

接近

TYPE_PROXIMITY

SENSOR_TTYPE_PROXIMITY

8

重力传感

直线加速度

旋转矢量传感器

NFC(nearfieldcommunication)近场通信

传感器的系统结构

传感器系统的java部分

代码路径为:\frameworks\base\core\java\android\hardware

传感器系统的JNI部分

代码路径为:\frameworks\base\core\jni\android_hardware_SensorManager.cpp

传感器系统的底层部分

代码路径为:\frameworks\base\include\gui

 

传感器的系统层次结构

传感器系统的各个层次,自下而上为:

驱动程序

硬件抽象层

JNI

JAVA

框架层对传感器器的应用

应用对传感器的应用

注本地部分已包含在JNI层中没有单独的实现库

 

 

传感器的JNI

直接调用硬件抽象层,包含头文件sensor.h头文件该文件的路径为:ardware\libhardware\include\hardware

staticJNINativeMethodgMethods[]={

{"nativeClassInit","()V",(void*)nativeClassInit},

{"sensors_module_init","()I",(void*)sensors_module_init},

{"sensors_module_get_next_sensor","(Landroid/hardware/Sensor;I)I",

(void*)sensors_module_get_next_sensor},

 

{"sensors_create_queue","()I",(void*)sensors_create_queue},

{"sensors_destroy_queue","(I)V",(void*)sensors_destroy_queue},

{"sensors_enable_sensor","(ILjava/lang/String;II)Z",

(void*)sensors_enable_sensor},

 

{"sensors_data_poll","(I[F[I[J)I",(void*)sensors_data_poll},

};

这些方法主要是供java层的sensorManager.java

 

staticjint

sensors_module_init(JNIEnv*env,jclassclazz)

{

SensorManager::getInstance();

return0;

}

 

调用hw_get_module()函数是硬件模块的通用接口,根据传感器硬件模块的标识SENSORS_HARDWARE_MODULE_ID打开这个硬件模块

传感器系统的java代码

代码的路径为:\frameworks\base\core\java\android\hardware

sensorManager.java传感器的核心管理类

Sensor.java传感器的实体类

sensorEvent.java传感器的事件类

(接口)

sensorEventListener.java传感器事件的监听者

sensorListener.java传感器的监听者(不推荐使用)

 

 

sensorManager.java的几个主要方法:

publicclassSensorManager{

publicSensorgetDefaultSensor(inttype){}//取得默认传感器

publicList<Sensor>getSensorList(inttype){}//取默认传感器列表

 

以下两个方法使用sensorEventListener接口作为传感器的监听者

publicbooleanregisterListener(SensorListenerlistener,intsensors){}//注册传感器的监听者

publicvoidunregisterListener(SensorListenerlistener,intsensors){}//注销注册监听

 

在这个类中还定义了一些常量

publicstaticfinalfloatGRAVITY_***//重力常量

publicstaticfinalfloatMAGNETIC_***磁场常量

publicstaticfinalfloatLIGHT_***//亮度传感器

 

 

publicclassSensor{

//以下是android支持的十一种传感器类型

publicstaticfinalintTYPE_ACCELEROMETER=1;

publicstaticfinalintTYPE_MAGNETIC_FIELD=2;

publicstaticfinalintTYPE_ORIENTATION=3;

publicstaticfinalintTYPE_GYROSCOPE=4;

publicstaticfinalintTYPE_LIGHT=5;

publicstaticfinalintTYPE_PRESSURE=6;

publicstaticfinalintTYPE_TEMPERATURE=7;

publicstaticfinalintTYPE_PROXIMITY=8;

publicstaticfinalintTYPE_GRAVITY=9;

publicstaticfinalintTYPE_LINEAR_ACCELERATION=10;

publicstaticfinalintTYPE_ROTATION_VECTOR=11;

//所有传感器类型

publicstaticfinalintTYPE_ALL=-1;

 

 

 

privateStringmName;//名称

privateStringmVendor;//

privateintmVersion;//版本

privateintmType;//类型

privatefloatmMaxRange;//取得传感器的最大范围

privatefloatmResolution;//传感器的解析度

privateintmHandle;//

//以下是2.3版本中新添加

privatefloatmPower;

privateintmMinDelay;

privateintmLegacyType;

}

 

//传感器监听

publicinterfaceSensorEventListener{

//数值发生变化时调用

publicvoidonSensorChanged(SensorEventevent);

//传感器精度发生变化时调用

publicvoidonAccuracyChanged(Sensorsensor,intaccuracy);

}

 

 

传感器系统的硬件抽象层

代码路径如下:\hardware\libhardware\include\hardware

Sensors.h头文件的部分路径如下:

 

//定义传感器类型

#defineSENSOR_TYPE_ACCELEROMETER1

#defineSENSOR_TYPE_MAGNETIC_FIELD2

#defineSENSOR_TYPE_ORIENTATION3

#defineSENSOR_TYPE_GYROSCOPE4

#defineSENSOR_TYPE_LIGHT5

#defineSENSOR_TYPE_PRESSURE6

#defineSENSOR_TYPE_TEMPERATURE7

#defineSENSOR_TYPE_PROXIMITY8

#defineSENSOR_TYPE_GRAVITY9

#defineSENSOR_TYPE_LINEAR_ACCELERATION10

#defineSENSOR_TYPE_ROTATION_VECTOR11

 

 

//hw_module_tcommon标准的硬件模块

structsensors_module_t{

structhw_module_tcommon;

//获取传感器列表

int(*get_sensors_list)(structsensors_module_t*module,

structsensor_tconst**list);

};

 

//传感器的描述性定义

structsensor_t{

constchar*name;

constchar*vendor;

intversion;

inthandle;//传感器的句柄

inttype;

floatmaxRange;

floatresolution;

floatpower;//能耗ma

int32_tminDelay;

void*reserved[8];

};

 

 

//表示传感器的数据

union{

floatdata[16];

sensors_vec_tacceleration;//方向

sensors_vec_tmagnetic;//磁矢量

sensors_vec_torientation;//加速度

sensors_vec_tgyro;//陀螺仪

floattemperature;//温度

floatdistance;//距离

floatlight;//亮度

floatpressure;//压强

};

uint32_treserved1[4];

}sensors_event_t;

 

//用户控制设备

structsensors_poll_device_t{

structhw_device_tcommon;

int(*activate)(structsensors_poll_device_t*dev,

inthandle,intenabled);

 

int(*setDelay)(structsensors_poll_device_t*dev,

inthandle,int64_tns);

 

 

int(*poll)(structsensors_poll_device_t*dev,

sensors_event_t*data,intcount);

};

 

 

//用于打开和关闭传感器设备,打开的过程从native_handle_t开始,pull函数是核心,

调用时被子阻塞,直到传感器获得数据返回

staticinlineintsensors_open(conststructhw_module_t*module,

structsensors_poll_device_t**device){

returnmodule->methods->open(module,

SENSORS_HARDWARE_POLL,(structhw_device_t**)device);

}

 

staticinlineintsensors_close(structsensors_poll_device_t*device){

returndevice->common.close(&device->common);

}

 

 

硬件抽象层的示例实现

模似器提供了一个示例实现,代码路径为:sdk\emulator\sensors

//

staticstructhw_module_methods_tsensors_module_methods={

.open=open_sensors

};

 

open_sensors函数用于构建控制设备和数据设备

staticint

open_sensors(conststructhw_module_t*module,

constchar*name,

structhw_device_t**device)

{

intstatus=-EINVAL;

 

D("%s:name=%s",__FUNCTION__,name);

 

if(!strcmp(name,SENSORS_HARDWARE_CONTROL))

{

SensorControl*dev=malloc(sizeof(*dev));

 

memset(dev,0,sizeof(*dev));

 

dev->device.common.tag=HARDWARE_DEVICE_TAG;

dev->device.common.version=0;

dev->device.common.module=(structhw_module_t*)module;

dev->device.common.close=control__close;

dev->device.open_data_source=control__open_data_source;

dev->device.activate=control__activate;

dev->device.set_delay=control__set_delay;

dev->device.wake=control__wake;

dev->fd=-1;

 

*device=&dev->device.common;

status=0;

}

elseif(!strcmp(name,SENSORS_HARDWARE_DATA)){

SensorData*dev=malloc(sizeof(*dev));

 

memset(dev,0,sizeof(*dev));

 

dev->device.common.tag=HARDWARE_DEVICE_TAG;

dev->device.common.version=0;

dev->device.common.module=(structhw_module_t*)module;

dev->device.common.close=data__close;

dev->device.data_open=data__data_open;

dev->device.data_close=data__data_close;

dev->device.poll=data__poll;

dev->events_fd=-1;

 

*device=&dev->device.common;

status=0;

}

returnstatus;

}

 

 

//定义取得传感器列表的函数指针

conststructsensors_module_tHAL_MODULE_INFO_SYM={

.common={

.tag=HARDWARE_MODULE_TAG,

.version_major=1,

.version_minor=0,

.id=SENSORS_HARDWARE_MODULE_ID,

.name="GoldfishSENSORSModule",

.author="TheAndroidOpenSourceProject",

.methods=&sensors_module_methods,

},

.get_sensors_list=sensors__get_sensors_list

};

 

 

staticuint32_tsensors__get_sensors_list(structsensors_module_t*module,

structsensor_tconst**list)

{

intfd=qemud_channel_open(SENSORS_SERVICE_NAME);

charbuffer[12];

intmask,nn,count;

 

intret;

if(fd<0){

E("%s:noqemudconnection",__FUNCTION__);

return0;

}

ret=qemud_channel_send(fd,"list-sensors",-1);

if(ret<0){

E("%s:couldnotquerysensorlist:%s",__FUNCTION__,

strerror(errno));

close(fd);

return0;

}

ret=qemud_channel_recv(fd,buffer,sizeofbuffer-1);

if(ret<0){

E("%s:couldnotreceivesensorlist:%s",__FUNCTION__,

strerror(errno));

close(fd);

return0;

}

buffer[ret]=0;

close(fd);

 

/*theresultisaintegerusedasamaskforavailablesensors*/

mask=atoi(buffer);

count=0;

for(nn=0;nn<MAX_NUM_SENSORS;nn++){

if(((1<<nn)&mask)==0)

continue;

 

sSensorList[count++]=sSensorListInit[nn];

}

D("%s:returned%dsensors(mask=%d)",__FUNCTION__,count,mask);

*list=sSensorList;

returncount;

}

 

 

最后返回的是一个sensor_t类型的数组,部分代码如下(定义了四个传感器):

staticconststructsensor_tsSensorListInit[]={

//加速度

{.name="Goldfish3-axisAccelerometer",

.vendor="TheAndroidOpenSourceProject",

.version=1,

.handle=ID_ACCELERATION,

.type=SENSOR_TYPE_ACCELEROMETER,

.maxRange=2.8f,

.resolution=1.0f/4032.0f,

.power=3.0f,

.reserved={}

},

//磁场

{.name="Goldfish3-axisMagneticfieldsensor",

.vendor="TheAndroidOpenSourceProject",

.version=1,

.handle=ID_MAGNETIC_FIELD,

.type=SENSOR_TYPE_MAGNETIC_FIELD,

.maxRange=2000.0f,

.resolution=1.0f,

.power=6.7f,

.reserved={}

},

//方向

{.name="GoldfishOrientationsensor",

.vendor="TheAndroidOpenSourceProject",

.version=1,

.handle=ID_ORIENTATION,

.type=SENSOR_TYPE_ORIENTATION,

.maxRange=360.0f,

.resolution=1.0f,

.power=9.7f,

.reserved={}

},

 

//温度

{.name="GoldfishTemperaturesensor",

.vendor="TheAndroidOpenSourceProject",

.version=1,

.handle=ID_TEMPERATURE,

.type=SENSOR_TYPE_TEMPERATURE,

.maxRange=80.0f,

.resolution=1.0f,

.power=0.0f,

.reserved={}

},

};

 

 

 

 

staticint

data__poll(structsensors_data_device_t*dev,sensors_data_t*values)

{

SensorData*data=(void*)dev;

intfd=data->events_fd;

 

D("%s:data=%p",__FUNCTION__,dev);

 

//therearependingsensors,returnsthemnow...

if(data->pendingSensors){

returnpick_sensor(data,values);

}

 

//waituntilwegetacompleteeventforanenabledsensor

uint32_tnew_sensors=0;

//读取传感器信息,设置sensor_data_t结构体数据

while(1){

/*readthenextevent*/

charbuff[256];

intlen=qemud_channel_recv(data->events_fd,buff,sizeofbuff-1);

floatparams[3];

int64_tevent_time;

 

if(len<0){

E("%s:len=%d,errno=%d:%s",__FUNCTION__,len,errno,strerror(errno));

return-errno;

}

 

buff[len]=0;

 

/*"wake"issentfromtheemulatortoexitthisloop.Thisshall

*reallybebecauseanotherthreadcalled"control__wake"inthis

*process.

*/

if(!strcmp((constchar*)data,"wake")){

return0x7FFFFFFF;

}

 

/*"acceleration:<x>:<y>:<z>"correspondstoanaccelerationevent*/

if(sscanf(buff,"acceleration:%g:%g:%g",params+0,params+1,params+2)==3){

new_sensors|=SENSORS_ACCELERATION;

data->sensors[ID_ACCELERATION].acceleration.x=params[0];

data->sensors[ID_ACCELERATION].acceleration.y=params[1];

data->sensors[ID_ACCELERATION].acceleration.z=params[2];

continue;

}

 

/*"orientation:<azimuth>:<pitch>:<roll>"issentwhenorientationchanges*/

if(sscanf(buff,"orientation:%g:%g:%g",params+0,params+1,params+2)==3){

new_sensors|=SENSORS_ORIENTATION;

data->sensors[ID_ORIENTATION].orientation.azimuth=params[0];

data->sensors[ID_ORIENTATION].orientation.pitch=params[1];

data->sensors[ID_ORIENTATION].orientation.roll=params[2];

continue;

}

 

/*"magnetic:<x>:<y>:<z>"issentfortheparamsofthemagneticfield*/

if(sscanf(buff,"magnetic:%g:%g:%g",params+0,params+1,params+2)==3){

new_sensors|=SENSORS_MAGNETIC_FIELD;

data->sensors[ID_MAGNETIC_FIELD].magnetic.x=params[0];

data->sensors[ID_MAGNETIC_FIELD].magnetic.y=params[1];

data->sensors[ID_MAGNETIC_FIELD].magnetic.z=params[2];

continue;

}

 

/*"temperature:<celsius>"*/

if(sscanf(buff,"temperature:%g",params+0)==2){

new_sensors|=SENSORS_TEMPERATURE;

data->sensors[ID_TEMPERATURE].temperature=params[0];

continue;

}

 

/*"sync:<time>"issentafteraseriesofsensorevents.

*where'time'isexpressedinmicro-secondsandcorresponds

*totheVMtimewhentherealpolloccured.

*/

if(sscanf(buff,"sync:%lld",&event_time)==1){

if(new_sensors){

data->pendingSensors=new_sensors;

int64_tt=event_time*1000LL;/*converttonano-seconds*/

 

/*usethetimeatthefirstsync:asthebaseforlater

*timevalues*/

if(data->timeStart==0){

data->timeStart=data__now_ns();

data->timeOffset=data->timeStart-t;

}

t+=data->timeOffset;

 

while(new_sensors){

uint32_ti=31-__builtin_clz(new_sensors);

new_sensors&=~(1<<i);

data->sensors[i].time=t;

}

returnpick_sensor(data,values);

}else{

D("huh?syncwithoutanysensordata?");

}

continue;

}

D("huh?unsupportedcommand");

}

}

 

传感器硬件层实现的要点

1可以支持多个传感器,也可支多个同类型的传感器,需要构建一个sensor_t类型的数组

2传感器的控制设备和数据设备可能被扩展,用来保存传感器抽象层的上下文

前提是sensor_control_device_tsensors_data_device_t两个数据结构需要作为扩展结构体的第一个成员

3传感器在linux内核的驱动程序很可能使用misc驱动程序这时需要在开发控制设备时,同样使用open打开传感器的设备结点

4传感器数据设备poll指针是实现的重点,传感器在没有数据变化时实现阻塞,在数据变化时返回,

根据驱动程序的情况可以使用poll,read或者ioctl等接口来实现,这些驱动程序可以实现相应的阻塞

当传感器控制设备的wake()被调用时,需要让数据设备的pool立即返回0x7fffffff

 

 

传感器的使用

 

 

取得SensorManager(系统服务)

sensorManager=(SensorManager)this.getSystemService(Context.SENSOR_SERVICE);

OrientationEventListener扩展了sensorEventListener

publicOrientationEventListener(Contextcontext,intrate){

//取得传感器服务

mSensorManager=(SensorManager)context.getSystemService(Context.SENSOR_SERVICE);

mRate=rate;

//取得加速度传感器

mSensor=mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

if(mSensor!=null){

//Createlisteneronlyifsensorsdoexist

mSensorEventListener=newSensorEventListenerImpl();

}

}

 

 

//注册传感器的监听事件

publicvoidenable(){

if(mSensor==null){

Log.w(TAG,"Cannotdetectsensors.Notenabled");

return;

}

if(mEnabled==false){

if(localLOGV)Log.d(TAG,"OrientationEventListenerenabled");

mSensorManager.registerListener(mSensorEventListener,mSensor,mRate);

mEnabled=true;

}

}

 

classSensorEventListenerImplimplementsSensorEventListener{

//通过加速度信信息取得方向信息

publicvoidonSensorChanged(SensorEventevent){}

}

在清单文件中设置activity属性

android:screenOrientation="sensor"//根据传感器设置屏幕方向

如果属性设置为nosensor则不会改变方向

分享到:
评论

相关推荐

    第一行代码 android学习笔记 完整版

    Android学习笔记是Android开发者的必读书籍,书中涵盖了Android系统架构、Activity、Intent、资源管理等多方面的知识。本笔记对应的学习资源《第一行代码》是Android开发者的入门必读书籍,书中系统地介绍了Android...

    Android基础学习笔记

    Android基础学习笔记主要涵盖了一系列关于Android开发的基本概念和关键组件,以下是这些知识点的详细解析: 1. **Activity**: 是Android应用程序的基本单元,它代表用户在屏幕上看到的一个界面。每个Activity都必须...

    Android Studio 学习笔记-新手入门-(1)第一个案例

    这篇学习笔记将引导新手入门,通过创建第一个简单的案例来了解Android Studio的基本操作。 首先,让我们了解一下Android Studio的核心功能。它基于IntelliJ IDEA,具备代码自动补全、重构、调试等强大的开发特性。...

    Android Activity学习笔记

    Android Activity学习笔记 Android Activity是Android系统中最基本的组件之一,它负责处理用户交互和显示用户界面。本文将深入讲解Activity的生命周期、Activity之间的数据交互、Activity启动模式、Task和BackStack...

    Android学习新手笔记

    - Android系统基于Linux系统开发,拥有开放源码。 - Android系统框架由多个组件构成,其中包括Activity、Intent、Service、ContentProvider、View和BroadcastReceiver。 - Activity作为组件容器,主要负责用户...

    java学习细节 android学习笔记

    根据给定的信息,我们可以从Java和Android学习笔记中提取出一系列重要的知识点,下面将逐一进行详细解释。 ### Java基础知识 #### 1. 命令行基础操作 - **`javacmd`**: 这个命令是Java命令行工具的一部分,用于...

    Android+学习笔记

    ### Android学习笔记知识点详解 #### 一、简介与背景 Android作为全球最受欢迎的移动操作系统之一,自2007年谷歌发布以来,迅速占领市场并持续引领移动技术的发展。随着移动互联网的兴起和发展,Android应用开发...

    Android_学习笔记

    ### Android学习笔记——从HelloWorld开始 #### 一、Google的Android SDK介绍 自从Google发布了Android SDK以来,这款开源移动操作系统迅速吸引了众多开发者的关注。Android SDK为开发者提供了丰富的工具和API,...

    android全程学习笔记

    Android全程学习笔记旨在提供一个详尽且全面的指南,涵盖了Android开发中的关键技术点和实践案例。以下是关于Android开发的一些核心知识点: 1. **第一个Android应用**:开发Android应用的起点通常是从创建并运行你...

    Android_学习笔记.zip

    这个"Android_学习笔记.zip"文件很可能包含了一个详细的Android开发学习路径和关键知识点的总结。下面将基于这个主题,详细讲解Android开发的一些核心概念和技术。 首先,Android是Google开发的一款开源操作系统,...

    Android 学习笔记

    这篇学习笔记主要涵盖了关于布局的一些基本概念,特别是`fill_parent`和`wrap_content`这两种尺寸指定方式,以及如何通过XML布局文件来精确控制组件的位置。 首先,`fill_parent`和`wrap_content`是Android布局中的...

    Android 系统相关学习笔记.zip

    在Android系统相关学习笔记中,我们可以深入探讨这个广泛而复杂的移动操作系统的核心概念和技术。Android以其开源性和灵活性,吸引了大量的开发者和爱好者。以下是一些关键的知识点: 1. **Android架构**:Android...

    android 很好的学习笔记

    【Android学习笔记详解】 在移动应用开发领域,Android操作系统占据着重要的地位,为开发者提供了...通过系统学习并实践其中的内容,你将能够逐步掌握Android开发的核心技能,为你的Android开发者之路打下坚实的基础。

    Android PreferenceActivity 学习笔记

    这篇学习笔记将深入探讨PreferenceActivity的使用方法、功能以及与源码相关的知识。 首先,PreferenceActivity是Android SDK提供的一种特殊类型的Activity,它允许开发者快速构建具有可配置选项的界面,类似于系统...

    Android开发学习笔记

    ### Android开发学习笔记知识点梳理 #### 一、Android概述与架构 - **定义与发布**:Android是由Google在2007年11月5日宣布的基于Linux平台的开源手机操作系统。它不仅用于智能手机,还广泛应用于平板电脑、可穿戴...

Global site tag (gtag.js) - Google Analytics