- 浏览: 365738 次
- 性别:
- 来自: 福州
文章分类
最新评论
-
loveskey:
找了好久,可算是找到了。感谢
dx.jar dx.bat -
zhaoyi168:
可以把工程的代码发给我吗?
ZJLN1982@yahoo.co ...
Athrun Demo -
ergodic09:
請問樓主 我目前在porting AR6003但是無法自己產生 ...
009-Android平台开发-WIFI function porting-WIFI功能移植 -
iedj99fei:
...
androi中xliff:g
下面是一篇关于Android传感器源码总结的文章,讲解得很详细,从Framework到HAL的接口,估计作者没有对sensors的HAL进行研究或者其他原因而没有对HAL更多说明。本人最近项目中有这个模块,先收藏下,以学习!
(原文)虽然这篇文章写得很差,因为赶时间,所以就匆匆忙忙地写出来自己作一个笔记。但是我想对大家应该有一点帮助。
1、有关sensor在Java应用程序的编程(以注册多个传感器为例,这程序是我临时弄出来的,可能有错)
package com.sensors.acc;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.hardware.SensorManager;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
public class acc extends Activity {
float x, y, z;
SensorManager sensormanager = null;
Sensor accSensor = null;
Sensor lightSensor = null;
Sensor proximitySensor = null;
TextView accTextView = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
sensormanager = (SensorManager)getSystemService(SENSOR_SERVICE);
accSensor = sensormanager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
lightSensor = sensormanager.getDefaultSensor(Sensor.TYPE_LIGHT);
proximitySensor = sensormanager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
accTextView = (TextView)findViewById(R.id.textview_name);
}
SensorEventListener lsn = new SensorEventListener() {
public void onSensorChanged(SensorEvent e) {
if (e.sensor == accSensor) {
Log.d("sensor", "found acc sensor");
x = e.values[SensorManager.DATA_X];
y = e.values[SensorManager.DATA_Y];
z = e.values[SensorManager.DATA_Z];
accTextView.setText("x = " + x + ", /ny = " + y + ", /nz = " + z);
}
else if (e.sensor == lightSensor) {
Log.d("sensor", "found light sensor");
accTextView.setText("data is " + e.values[0]);
}
else if (e.sensor == proximitySensor) {
Log.d("sensor", "found proximity sensor");
accTextView.setText("distance is " + e.values[0]);
}
// Log.d("sensor", "found acc sensor");
// Log.d("sensor", "x = " + x + ", y = " + y + ", z = " + z);
// accTextView.setText("x = " + x + ", /ny = " + y + ", /nz = " + z);
}
public void onAccuracyChanged(Sensor s, int accuracy) {
}
};
@Override
protected void onResume() {
super.onResume(); // register this class as a listener for the orientation and accelerometer sensors
sensormanager.registerListener(lsn, accSensor, SensorManager.SENSOR_DELAY_NORMAL);
sensormanager.registerListener(lsn, lightSensor, SensorManager.SENSOR_DELAY_NORMAL);
sensormanager.registerListener(lsn, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL);
// sensormanager.unregisterListener(lsn);
}
@Override
protected void onStop() { // unregister listener
sensormanager.unregisterListener(lsn, accSensor);
sensormanager.unregisterListener(lsn, lightSensor);
sensormanager.unregisterListener(lsn, proximitySensor);
super.onStop();
}
}
在onCreate()函数中,调用getSystemService(SENSOR_SERVICE)初始化一个SensorManager实例,为什么要用getSystemService函数,而不直接用new SensorManager呢?我们看此函数的实现,在ApplicationContext.java中,
if (SENSOR_SERVICE.equals(name)) {
return getSensorManager();
然后getSensorManager()的实现
private SensorManager getSensorManager() {
synchronized (mSync) {
if (mSensorManager == null) {
mSensorManager = new SensorManager(mMainThread.getHandler().getLooper());
}
}
return mSensorManager;
}
看到没有?初始化SensorManager的时候需要mMainThread.getHandler().getLooper()这个参数,之个应该是用来传递消息用的,在SensorManager类的构造函数中会把此参数传给类成员mMainLooper。如果用new SensorManager()就需要另外获取mainLooper参数传递进去。
2、在android中跟sensor有关的一些文件有SensorManager.java,位于frameworks/base/core/java/android/hardware目录下,SensorService.java,位于frameworks/base/services/java/com/android/server目录下,android_hardware_SensorManager.cpp,位于frameworks/base/core/jni/目录下,与SensorManager.java相对应,com_android_server_SensorService.cpp,在frameworks/base/services/jni/目录下,与SensorService.java相对应。还有SystemServer.java文件,Hardware/Libhardware/Include/Hardware目录下的Sensor.h头文件。另外我们需要根据Sensor.h实现自己的一个源文件,一般取名为sensors_xxx.c或者sensors_xxx.cpp。
3、SensorManager类分析
有几个函数比较重要,必须清晰理解它们的实现,才能了解整个传感器系统的实现。从而更好地去实现硬件抽象层的实现。几个比较重要的函数有构造函数SensorManager(), registerListener()和unregisterListener(),其中registerListener()和unregisterListener()有多个,标志为 @Deprecated的是过时的,就不要看了。
(1)构造函数SensorManager(Looper mainLooper)
这个函数首先获取得传感器系统服务,并赋给类成员mSensorService,
mSensorService = ISensorService.Stub.asInterface(
ServiceManager.getService(Context.SENSOR_SERVICE));
这里我要说一句,就是关于这个传感器系统服务,很多书上都说用getSystemService()是获得传感器的系统服务,而它返回的是SensorManager类型,所以以为整个系统都是使用同一个SensorManager类的实例,以为我们在任何地方使用的SensorManager实例都是同一个,它们的公共成员是共享的。但是经过这两天的分析,这种说法是错误的。其实每次调用getSystemService()函数时都初始化一个新的SensorManager实例,而这个SensorManager实例会在构造函数里通过取得传感器系统服务SensorService来实现对下层传感器的一些控制。而这个SensorService才是系统的传感器服务,说服务,不如说它只是SensorService类的一个实例罢了。它只在系统初始化时初始化一次。Android中的系统服务机制应该跟传感器的都差不多一个样,都是由不同的Manager调用下层相同的Service。你可以列举其它的Manager。那它是什么时候初始化呢?它是系统初始化在SystemServer进程里创建的,SystemServer是一个管理很多系统服务的进程,我们转到SystemServer.的main函数里,可以看到一直到调用int2()函数,它会创建一个ServerThread,最终调用AdbSettingsObserver类的run()函数,在run()函数里有这么有一句
// Sensor Service is needed by Window Manager, so this goes first
Log.i(TAG, "Sensor Service");
ServiceManager.addService(Context.SENSOR_SERVICE, new SensorService(context));
这里就创建SensorService实例了。在创建这个实例时会在SensorService构造函数中调用jni函数 public SensorService(Context context) {
if (localLOGV) Log.d(TAG, "SensorService startup");
_sensors_control_init();
}
我们看_sensors_control_init();对应的为
static jint
android_init(JNIEnv *env, jclass clazz)
{
sensors_module_t* module;
if (hw_get_module(SENSORS_HARDWARE_MODULE_ID, (const hw_module_t**)&module) == 0) {
if (sensors_control_open(&module->common, &sSensorDevice) == 0) {
const struct sensor_t* list;
int count = module->get_sensors_list(module, &list);
return count;
}
}
return 0;
}
它主要调用了sensor.h中的sensors_control_open()
static inline int sensors_control_open(const struct hw_module_t* module,
struct sensors_control_device_t** device) {
return module->methods->open(module,
SENSORS_HARDWARE_CONTROL, (struct hw_device_t**)device);
}
之后在系统任何地方使用的都是这个SensorService实例。最后run()函数调用Looper.loop();就进行消息循环等待了,这就是SystemServer进程的消息服务了。这才真正叫做系统服务嘛。
我们继续看SensorManager类的构造函数,取得SensorService后,
nativeClassInit();
这是一个jni函数,SensorManager类调用的jni函数都在com_android_server_SensorService.cpp里,我们看这函数
static void
nativeClassInit (JNIEnv *_env, jclass _this)
{
jclass sensorClass = _env->FindClass("android/hardware/Sensor");
SensorOffsets& sensorOffsets = gSensorOffsets;
sensorOffsets.name = _env->GetFieldID(sensorClass, "mName", "Ljava/lang/String;");
sensorOffsets.vendor = _env->GetFieldID(sensorClass, "mVendor", "Ljava/lang/String;");
sensorOffsets.version = _env->GetFieldID(sensorClass, "mVersion", "I");
sensorOffsets.handle = _env->GetFieldID(sensorClass, "mHandle", "I");
sensorOffsets.type = _env->GetFieldID(sensorClass, "mType", "I");
sensorOffsets.range = _env->GetFieldID(sensorClass, "mMaxRange", "F");
sensorOffsets.resolution = _env->GetFieldID(sensorClass, "mResolution","F");
sensorOffsets.power = _env->GetFieldID(sensorClass, "mPower", "F");
}
这个函数只是获取和设置一些信息吧,我们不关心。接着
sensors_module_init();
我们看这函数
static jint
sensors_module_init(JNIEnv *env, jclass clazz)
{
int err = 0;
sensors_module_t const* module;
err = hw_get_module(SENSORS_HARDWARE_MODULE_ID, (const hw_module_t **)&module);
if (err == 0)
sSensorModule = (sensors_module_t*)module;
return err;
}
它获取了sensor的模块信息,并把它赋给sSensorModule全局变量,之后传的modules参数都为这个。
接着在构造函数里
final ArrayList<Sensor> fullList = sFullSensorsList;
int i = 0;
do {
Sensor sensor = new Sensor();
i = sensors_module_get_next_sensor(sensor, i);
if (i>=0) {
Log.d(TAG, "found sensor: " + sensor.getName() +
", handle=" + sensor.getHandle());
sensor.setLegacyType(getLegacySensorType(sensor.getType()));
fullList.add(sensor);
sHandleToSensor.append(sensor.getHandle(), sensor);
}
} while (i>0);
这里主要是通过jni函数sensors_module_get_next_sensor(sensor, i);获取传感器列表,并把它加入自己的fullList列表中。我们看sensors_module_get_next_sensor()函数
static jint
sensors_module_get_next_sensor(JNIEnv *env, jobject clazz, jobject sensor, jint next)
{
if (sSensorModule == NULL)
return 0;
SensorOffsets& sensorOffsets = gSensorOffsets;
const struct sensor_t* list;
int count = sSensorModule->get_sensors_list(sSensorModule, &list);
if (next >= count)
return -1;
list += next;
jstring name = env->NewStringUTF(list->name);
jstring vendor = env->NewStringUTF(list->vendor);
env->SetObjectField(sensor, sensorOffsets.name, name);
env->SetObjectField(sensor, sensorOffsets.vendor, vendor);
env->SetIntField(sensor, sensorOffsets.version, list->version);
env->SetIntField(sensor, sensorOffsets.handle, list->handle);
env->SetIntField(sensor, sensorOffsets.type, list->type);
env->SetFloatField(sensor, sensorOffsets.range, list->maxRange);
env->SetFloatField(sensor, sensorOffsets.resolution, list->resolution);
env->SetFloatField(sensor, sensorOffsets.power, list->power);
next++;
return next<count ? next : 0;
}
它主要是调用HAL层的get_sensors_list()函数取得传感器列表信息。
接着在sensorManger构造函数最后
sSensorThread = new SensorThread();
创建一个SensorThread()线程。但并未运行,但在SensorThread类的构造函数里会执行jni函数 sensors_data_init();
我们看此函数static jint
sensors_data_init(JNIEnv *env, jclass clazz)
{
if (sSensorModule == NULL)
return -1;
int err = sensors_data_open(&sSensorModule->common, &sSensorDevice);
return err;
}
它调用了HAL层的sensors_data_open函数,而这个函数位于sensor.h中,它调用的是
static inline int sensors_data_open(const struct hw_module_t* module,
struct sensors_data_device_t** device) {
return module->methods->open(module,
SENSORS_HARDWARE_DATA, (struct hw_device_t**)device);
}
Modules->methods->open函数。而在SensorThread类的析构函数finalize()里会调用
sensors_data_uninit();
static jint
sensors_data_uninit(JNIEnv *env, jclass clazz)
{
int err = 0;
if (sSensorDevice) {
err = sensors_data_close(sSensorDevice);
if (err == 0)
sSensorDevice = 0;
}
return err;
}
在sensor.h里
static inline int sensors_data_close(struct sensors_data_device_t* device) {
return device->common.close(&device->common);
}
那什么时候sSensorThread线程会运行呢?我们在下面看registerListener()函数。
(2) public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate) {
return registerListener(listener, sensor, rate, null);
}
它调用的是 public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate,
Handler handler)
在这函数中,先验证rate,然后检测注册的listener在不在本类的sListeners列表中。
for (ListenerDelegate i : sListeners) {
if (i.getListener() == listener) {
l = i;
break;
}
}
如果不在就申请一个listener,并把它加入全局列表sListener中,并调用mSensorService的enableSensor()函数使能传感器,这个enableSensor()函数最终会调用HAL层的active函数和set_delay()函数,使用后然后判断sListener列表是否为空,当然,第一次为空时加入一个新的listener就不为空了,此时就执行sSensorThread的startLocked运行sSensorThread线程了
l = new ListenerDelegate(listener, sensor, handler);
result = mSensorService.enableSensor(l, name, handle, delay);
if (result) {
sListeners.add(l);
sListeners.notify();
}
if (!sListeners.isEmpty()) {
sSensorThread.startLocked(mSensorService);
}
另一方面,如果注册的listener在sListeners列表中,则先调用mSensorService的enableSensor()函数使能传感器,然后把注册的传感器加入到已存在的listener中。
result = mSensorService.enableSensor(l, name, handle, delay);
if (result) {
l.addSensor(sensor);
}
接下来我们看看startLocked函数,它在SensorThread中,
void startLocked(ISensorService service) {
try {
if (mThread == null) {
Bundle dataChannel = service.getDataChannel();
mThread = new Thread(new SensorThreadRunnable(dataChannel),
SensorThread.class.getName());
mThread.start();
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in startLocked: ", e);
}
}
第一次mThread为null,然后它调用了service.getDataChannel()函数,此函数在SensorService类中,主要调用了jni函数_sensors_control_open(),
public Bundle getDataChannel() throws RemoteException {
// synchronize so we do not require sensor HAL to be thread-safe.
synchronized(mListeners) {
return _sensors_control_open();
}
}
SensorService类中调用的jni函数主要都在com_android_server_SensorService.cpp文件 中,我们看一下这个函数
static jobject
android_open(JNIEnv *env, jclass clazz)
{
native_handle_t* handle = sSensorDevice->open_data_source(sSensorDevice);
if (!handle) {
return NULL;
}
// new Bundle()
jobject bundle = env->NewObject(
gBundleOffsets.mClass,
gBundleOffsets.mConstructor);
if (handle->numFds > 0) {
jobjectArray fdArray = env->NewObjectArray(handle->numFds,
gParcelFileDescriptorOffsets.mClass, NULL);
for (int i = 0; i < handle->numFds; i++) {
// new FileDescriptor()
jobject fd = env->NewObject(gFileDescriptorOffsets.mClass,
gFileDescriptorOffsets.mConstructor);
env->SetIntField(fd, gFileDescriptorOffsets.mDescriptor, handle->data[i]);
// new ParcelFileDescriptor()
jobject pfd = env->NewObject(gParcelFileDescriptorOffsets.mClass,
gParcelFileDescriptorOffsets.mConstructor, fd);
env->SetObjectArrayElement(fdArray, i, pfd);
}
// bundle.putParcelableArray("fds", fdArray);
env->CallVoidMethod(bundle, gBundleOffsets.mPutParcelableArray,
env->NewStringUTF("fds"), fdArray);
}
if (handle->numInts > 0) {
jintArray intArray = env->NewIntArray(handle->numInts);
env->SetIntArrayRegion(intArray, 0, handle->numInts, &handle->data[handle->numInts]);
// bundle.putIntArray("ints", intArray);
env->CallVoidMethod(bundle, gBundleOffsets.mPutIntArray,
env->NewStringUTF("ints"), intArray);
}
// delete the file handle, but don't close any file descriptors
native_handle_delete(handle);
return bundle;
}
它主要调用了HAL层的open_data_source()函数。取得一些文件描述符等信息。
接下来SensorThread创建一个线程,调用start()就进入SensorThreadRunnable类的run()函数了,所以我们接着去看run()函数,它首先调用open()函数
if (!open()) {
return;
}
在open()函数中调用了 jni函数sensors_data_open(fds, ints);
static jint
sensors_data_open(JNIEnv *env, jclass clazz, jobjectArray fdArray, jintArray intArray)
{
jclass FileDescriptor = env->FindClass("java/io/FileDescriptor");
jfieldID fieldOffset = env->GetFieldID(FileDescriptor, "descriptor", "I");
int numFds = (fdArray ? env->GetArrayLength(fdArray) : 0);
int numInts = (intArray ? env->GetArrayLength(intArray) : 0);
native_handle_t* handle = native_handle_create(numFds, numInts);
int offset = 0;
for (int i = 0; i < numFds; i++) {
jobject fdo = env->GetObjectArrayElement(fdArray, i);
if (fdo) {
handle->data[offset++] = env->GetIntField(fdo, fieldOffset);
} else {
handle->data[offset++] = -1;
}
}
if (numInts > 0) {
jint* ints = env->GetIntArrayElements(intArray, 0);
for (int i = 0; i < numInts; i++) {
handle->data[offset++] = ints[i];
}
env->ReleaseIntArrayElements(intArray, ints, 0);
}
// doesn't take ownership of the native handle
return sSensorDevice->data_open(sSensorDevice, handle);
}
这函数最终调用了HAL层的data_open(),之后run()函数就进入一个while循环了。
while (true) {
// wait for an event
final int sensor = sensors_data_poll(values, status, timestamp);
int accuracy = status[0];
synchronized (sListeners) {
if (sensor == -1 || sListeners.isEmpty()) {
if (sensor == -1) {
// we lost the connection to the event stream. this happens
// when the last listener is removed.
Log.d(TAG, "_sensors_data_poll() failed, we bail out.");
}
// we have no more listeners or polling failed, terminate the thread
sensors_data_close();
mThread = null;
break;
}
final Sensor sensorObject = sHandleToSensor.get(sensor);
if (sensorObject != null) {
// report the sensor event to all listeners that
// care about it.
final int size = sListeners.size();
for (int i=0 ; i<size ; i++) {
ListenerDelegate listener = sListeners.get(i);
if (listener.hasSensor(sensorObject)) {
// this is asynchronous (okay to call
// with sListeners lock held).
listener.onSensorChangedLocked(sensorObject,
values, timestamp, accuracy);
}
}
}
}
它调用了jni函数sensors_data_poll()一直读数据。
static jint
sensors_data_poll(JNIEnv *env, jclass clazz,
jfloatArray values, jintArray status, jlongArray timestamp)
{
sensors_data_t data;
int res = sSensorDevice->poll(sSensorDevice, &data);
if (res >= 0) {
jint accuracy = data.vector.status;
env->SetFloatArrayRegion(values, 0, 3, data.vector.v);
env->SetIntArrayRegion(status, 0, 1, &accuracy);
env->SetLongArrayRegion(timestamp, 0, 1, &data.time);
}
return res;
}
把传感器得到的值都放在value数组中,根据返回的传感器标志sensor,把它分派给在sListener列表中所有的listener,如果listener中有监听这个sensor,就把它分派给这个listener,此时就会引起onSensorChange()了。
好了,获取传感器数据主要是这样一个途径。最后我们去分析一下unregisterListener()函数。
private void unregisterListener(Object listener) {
if (listener == null) {
return;
}
try {
synchronized (sListeners) {
final int size = sListeners.size();
for (int i=0 ; i<size ; i++) {
ListenerDelegate l = sListeners.get(i);
if (l.getListener() == listener) {
// disable all sensors for this listener
for (Sensor sensor : l.getSensors()) {
String name = sensor.getName();
int handle = sensor.getHandle();
mSensorService.enableSensor(l, name, handle, SENSOR_DISABLE);
}
sListeners.remove(i);
break;
}
}
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in unregisterListener: ", e);
}
}
不用想这个函数会做一些与registerListener相反的事情,至少差不多。它先在sListeners列表中找到这个listener,然后先调用enableSensor()函数禁止这个传感器。我们跟踪一下这函数,在SensorService类中。
synchronized(mListeners) {
if (enable!=SENSOR_DISABLE && !_sensors_control_activate(sensor, true)) {
Log.w(TAG, "could not enable sensor " + sensor);
return false;
}
Listener l = null;
int minDelay = enable;
for (Listener listener : mListeners) {
if (binder == listener.mToken) {
l = listener;
}
if (minDelay > listener.mDelay)
minDelay = listener.mDelay;
}
if (l == null && enable!=SENSOR_DISABLE) {
l = new Listener(binder);
binder.linkToDeath(l, 0);
mListeners.add(l);
mListeners.notify();
}
if (l == null) {
// by construction, this means we're disabling a listener we
// don't know about...
Log.w(TAG, "listener with binder " + binder +
", doesn't exist (sensor=" + name + ", id=" + sensor + ")");
return false;
}
if (minDelay >= 0) {
_sensors_control_set_delay(minDelay);
}
if (enable != SENSOR_DISABLE) {
l.addSensor(sensor, enable);
} else {
l.removeSensor(sensor);
deactivateIfUnusedLocked(sensor);
if (l.mSensors == 0) {
mListeners.remove(l);
binder.unlinkToDeath(l, 0);
mListeners.notify();
}
}
if (mListeners.size() == 0) {
_sensors_control_wake();
_sensors_control_close();
}
}
return true;
你们看到它的实现了吧。如果enable是true的话,就调用_sensors_control_activate(),如果是false的话,就调用deactivateIfUnusedLocked(),它们最终都会调用 HAL层的active()函数。最后,如果是禁止传感器的话,如果mListeners为空了,它就会调用
_sensors_control_wake();
_sensors_control_close();
这两个jni函数,最终会调用HAL层的wake()和close_data_source()函数。当调用wake()函数时,会使SensorManager类线程的run()函数中的sensor_data_poll()函数立即返回,此时在run()函数中调用sensors_data_close();最终会调用HAL层的data_close()函数。至此,一个传感器从初始到结束的流程就分析完了。
所以在java使用一个传感器在HAL层具体调用的函数流程为:
首先,sensors_control_open(),只在系统初始化时调用一次。用来初始化control_device结构体。
以下的是每次使用传感器一般经过的流程,注意,是一般而已,有些并不执行
(1)sensors_data_open
(2)get_sensors_list
(3)activate
(4)set_delay
(5)open_data_source
(6)data_open
(7)poll
一直读数据。。。。。。。。。。。
退出时
(8)activate
(9)sensors_control_close
(10)data_close
原文:http://blog.csdn.net/JerryMo06/archive/2010/04/15/5487476.aspx
(原文)虽然这篇文章写得很差,因为赶时间,所以就匆匆忙忙地写出来自己作一个笔记。但是我想对大家应该有一点帮助。
1、有关sensor在Java应用程序的编程(以注册多个传感器为例,这程序是我临时弄出来的,可能有错)
package com.sensors.acc;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.hardware.SensorManager;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
public class acc extends Activity {
float x, y, z;
SensorManager sensormanager = null;
Sensor accSensor = null;
Sensor lightSensor = null;
Sensor proximitySensor = null;
TextView accTextView = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
sensormanager = (SensorManager)getSystemService(SENSOR_SERVICE);
accSensor = sensormanager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
lightSensor = sensormanager.getDefaultSensor(Sensor.TYPE_LIGHT);
proximitySensor = sensormanager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
accTextView = (TextView)findViewById(R.id.textview_name);
}
SensorEventListener lsn = new SensorEventListener() {
public void onSensorChanged(SensorEvent e) {
if (e.sensor == accSensor) {
Log.d("sensor", "found acc sensor");
x = e.values[SensorManager.DATA_X];
y = e.values[SensorManager.DATA_Y];
z = e.values[SensorManager.DATA_Z];
accTextView.setText("x = " + x + ", /ny = " + y + ", /nz = " + z);
}
else if (e.sensor == lightSensor) {
Log.d("sensor", "found light sensor");
accTextView.setText("data is " + e.values[0]);
}
else if (e.sensor == proximitySensor) {
Log.d("sensor", "found proximity sensor");
accTextView.setText("distance is " + e.values[0]);
}
// Log.d("sensor", "found acc sensor");
// Log.d("sensor", "x = " + x + ", y = " + y + ", z = " + z);
// accTextView.setText("x = " + x + ", /ny = " + y + ", /nz = " + z);
}
public void onAccuracyChanged(Sensor s, int accuracy) {
}
};
@Override
protected void onResume() {
super.onResume(); // register this class as a listener for the orientation and accelerometer sensors
sensormanager.registerListener(lsn, accSensor, SensorManager.SENSOR_DELAY_NORMAL);
sensormanager.registerListener(lsn, lightSensor, SensorManager.SENSOR_DELAY_NORMAL);
sensormanager.registerListener(lsn, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL);
// sensormanager.unregisterListener(lsn);
}
@Override
protected void onStop() { // unregister listener
sensormanager.unregisterListener(lsn, accSensor);
sensormanager.unregisterListener(lsn, lightSensor);
sensormanager.unregisterListener(lsn, proximitySensor);
super.onStop();
}
}
在onCreate()函数中,调用getSystemService(SENSOR_SERVICE)初始化一个SensorManager实例,为什么要用getSystemService函数,而不直接用new SensorManager呢?我们看此函数的实现,在ApplicationContext.java中,
if (SENSOR_SERVICE.equals(name)) {
return getSensorManager();
然后getSensorManager()的实现
private SensorManager getSensorManager() {
synchronized (mSync) {
if (mSensorManager == null) {
mSensorManager = new SensorManager(mMainThread.getHandler().getLooper());
}
}
return mSensorManager;
}
看到没有?初始化SensorManager的时候需要mMainThread.getHandler().getLooper()这个参数,之个应该是用来传递消息用的,在SensorManager类的构造函数中会把此参数传给类成员mMainLooper。如果用new SensorManager()就需要另外获取mainLooper参数传递进去。
2、在android中跟sensor有关的一些文件有SensorManager.java,位于frameworks/base/core/java/android/hardware目录下,SensorService.java,位于frameworks/base/services/java/com/android/server目录下,android_hardware_SensorManager.cpp,位于frameworks/base/core/jni/目录下,与SensorManager.java相对应,com_android_server_SensorService.cpp,在frameworks/base/services/jni/目录下,与SensorService.java相对应。还有SystemServer.java文件,Hardware/Libhardware/Include/Hardware目录下的Sensor.h头文件。另外我们需要根据Sensor.h实现自己的一个源文件,一般取名为sensors_xxx.c或者sensors_xxx.cpp。
3、SensorManager类分析
有几个函数比较重要,必须清晰理解它们的实现,才能了解整个传感器系统的实现。从而更好地去实现硬件抽象层的实现。几个比较重要的函数有构造函数SensorManager(), registerListener()和unregisterListener(),其中registerListener()和unregisterListener()有多个,标志为 @Deprecated的是过时的,就不要看了。
(1)构造函数SensorManager(Looper mainLooper)
这个函数首先获取得传感器系统服务,并赋给类成员mSensorService,
mSensorService = ISensorService.Stub.asInterface(
ServiceManager.getService(Context.SENSOR_SERVICE));
这里我要说一句,就是关于这个传感器系统服务,很多书上都说用getSystemService()是获得传感器的系统服务,而它返回的是SensorManager类型,所以以为整个系统都是使用同一个SensorManager类的实例,以为我们在任何地方使用的SensorManager实例都是同一个,它们的公共成员是共享的。但是经过这两天的分析,这种说法是错误的。其实每次调用getSystemService()函数时都初始化一个新的SensorManager实例,而这个SensorManager实例会在构造函数里通过取得传感器系统服务SensorService来实现对下层传感器的一些控制。而这个SensorService才是系统的传感器服务,说服务,不如说它只是SensorService类的一个实例罢了。它只在系统初始化时初始化一次。Android中的系统服务机制应该跟传感器的都差不多一个样,都是由不同的Manager调用下层相同的Service。你可以列举其它的Manager。那它是什么时候初始化呢?它是系统初始化在SystemServer进程里创建的,SystemServer是一个管理很多系统服务的进程,我们转到SystemServer.的main函数里,可以看到一直到调用int2()函数,它会创建一个ServerThread,最终调用AdbSettingsObserver类的run()函数,在run()函数里有这么有一句
// Sensor Service is needed by Window Manager, so this goes first
Log.i(TAG, "Sensor Service");
ServiceManager.addService(Context.SENSOR_SERVICE, new SensorService(context));
这里就创建SensorService实例了。在创建这个实例时会在SensorService构造函数中调用jni函数 public SensorService(Context context) {
if (localLOGV) Log.d(TAG, "SensorService startup");
_sensors_control_init();
}
我们看_sensors_control_init();对应的为
static jint
android_init(JNIEnv *env, jclass clazz)
{
sensors_module_t* module;
if (hw_get_module(SENSORS_HARDWARE_MODULE_ID, (const hw_module_t**)&module) == 0) {
if (sensors_control_open(&module->common, &sSensorDevice) == 0) {
const struct sensor_t* list;
int count = module->get_sensors_list(module, &list);
return count;
}
}
return 0;
}
它主要调用了sensor.h中的sensors_control_open()
static inline int sensors_control_open(const struct hw_module_t* module,
struct sensors_control_device_t** device) {
return module->methods->open(module,
SENSORS_HARDWARE_CONTROL, (struct hw_device_t**)device);
}
之后在系统任何地方使用的都是这个SensorService实例。最后run()函数调用Looper.loop();就进行消息循环等待了,这就是SystemServer进程的消息服务了。这才真正叫做系统服务嘛。
我们继续看SensorManager类的构造函数,取得SensorService后,
nativeClassInit();
这是一个jni函数,SensorManager类调用的jni函数都在com_android_server_SensorService.cpp里,我们看这函数
static void
nativeClassInit (JNIEnv *_env, jclass _this)
{
jclass sensorClass = _env->FindClass("android/hardware/Sensor");
SensorOffsets& sensorOffsets = gSensorOffsets;
sensorOffsets.name = _env->GetFieldID(sensorClass, "mName", "Ljava/lang/String;");
sensorOffsets.vendor = _env->GetFieldID(sensorClass, "mVendor", "Ljava/lang/String;");
sensorOffsets.version = _env->GetFieldID(sensorClass, "mVersion", "I");
sensorOffsets.handle = _env->GetFieldID(sensorClass, "mHandle", "I");
sensorOffsets.type = _env->GetFieldID(sensorClass, "mType", "I");
sensorOffsets.range = _env->GetFieldID(sensorClass, "mMaxRange", "F");
sensorOffsets.resolution = _env->GetFieldID(sensorClass, "mResolution","F");
sensorOffsets.power = _env->GetFieldID(sensorClass, "mPower", "F");
}
这个函数只是获取和设置一些信息吧,我们不关心。接着
sensors_module_init();
我们看这函数
static jint
sensors_module_init(JNIEnv *env, jclass clazz)
{
int err = 0;
sensors_module_t const* module;
err = hw_get_module(SENSORS_HARDWARE_MODULE_ID, (const hw_module_t **)&module);
if (err == 0)
sSensorModule = (sensors_module_t*)module;
return err;
}
它获取了sensor的模块信息,并把它赋给sSensorModule全局变量,之后传的modules参数都为这个。
接着在构造函数里
final ArrayList<Sensor> fullList = sFullSensorsList;
int i = 0;
do {
Sensor sensor = new Sensor();
i = sensors_module_get_next_sensor(sensor, i);
if (i>=0) {
Log.d(TAG, "found sensor: " + sensor.getName() +
", handle=" + sensor.getHandle());
sensor.setLegacyType(getLegacySensorType(sensor.getType()));
fullList.add(sensor);
sHandleToSensor.append(sensor.getHandle(), sensor);
}
} while (i>0);
这里主要是通过jni函数sensors_module_get_next_sensor(sensor, i);获取传感器列表,并把它加入自己的fullList列表中。我们看sensors_module_get_next_sensor()函数
static jint
sensors_module_get_next_sensor(JNIEnv *env, jobject clazz, jobject sensor, jint next)
{
if (sSensorModule == NULL)
return 0;
SensorOffsets& sensorOffsets = gSensorOffsets;
const struct sensor_t* list;
int count = sSensorModule->get_sensors_list(sSensorModule, &list);
if (next >= count)
return -1;
list += next;
jstring name = env->NewStringUTF(list->name);
jstring vendor = env->NewStringUTF(list->vendor);
env->SetObjectField(sensor, sensorOffsets.name, name);
env->SetObjectField(sensor, sensorOffsets.vendor, vendor);
env->SetIntField(sensor, sensorOffsets.version, list->version);
env->SetIntField(sensor, sensorOffsets.handle, list->handle);
env->SetIntField(sensor, sensorOffsets.type, list->type);
env->SetFloatField(sensor, sensorOffsets.range, list->maxRange);
env->SetFloatField(sensor, sensorOffsets.resolution, list->resolution);
env->SetFloatField(sensor, sensorOffsets.power, list->power);
next++;
return next<count ? next : 0;
}
它主要是调用HAL层的get_sensors_list()函数取得传感器列表信息。
接着在sensorManger构造函数最后
sSensorThread = new SensorThread();
创建一个SensorThread()线程。但并未运行,但在SensorThread类的构造函数里会执行jni函数 sensors_data_init();
我们看此函数static jint
sensors_data_init(JNIEnv *env, jclass clazz)
{
if (sSensorModule == NULL)
return -1;
int err = sensors_data_open(&sSensorModule->common, &sSensorDevice);
return err;
}
它调用了HAL层的sensors_data_open函数,而这个函数位于sensor.h中,它调用的是
static inline int sensors_data_open(const struct hw_module_t* module,
struct sensors_data_device_t** device) {
return module->methods->open(module,
SENSORS_HARDWARE_DATA, (struct hw_device_t**)device);
}
Modules->methods->open函数。而在SensorThread类的析构函数finalize()里会调用
sensors_data_uninit();
static jint
sensors_data_uninit(JNIEnv *env, jclass clazz)
{
int err = 0;
if (sSensorDevice) {
err = sensors_data_close(sSensorDevice);
if (err == 0)
sSensorDevice = 0;
}
return err;
}
在sensor.h里
static inline int sensors_data_close(struct sensors_data_device_t* device) {
return device->common.close(&device->common);
}
那什么时候sSensorThread线程会运行呢?我们在下面看registerListener()函数。
(2) public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate) {
return registerListener(listener, sensor, rate, null);
}
它调用的是 public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate,
Handler handler)
在这函数中,先验证rate,然后检测注册的listener在不在本类的sListeners列表中。
for (ListenerDelegate i : sListeners) {
if (i.getListener() == listener) {
l = i;
break;
}
}
如果不在就申请一个listener,并把它加入全局列表sListener中,并调用mSensorService的enableSensor()函数使能传感器,这个enableSensor()函数最终会调用HAL层的active函数和set_delay()函数,使用后然后判断sListener列表是否为空,当然,第一次为空时加入一个新的listener就不为空了,此时就执行sSensorThread的startLocked运行sSensorThread线程了
l = new ListenerDelegate(listener, sensor, handler);
result = mSensorService.enableSensor(l, name, handle, delay);
if (result) {
sListeners.add(l);
sListeners.notify();
}
if (!sListeners.isEmpty()) {
sSensorThread.startLocked(mSensorService);
}
另一方面,如果注册的listener在sListeners列表中,则先调用mSensorService的enableSensor()函数使能传感器,然后把注册的传感器加入到已存在的listener中。
result = mSensorService.enableSensor(l, name, handle, delay);
if (result) {
l.addSensor(sensor);
}
接下来我们看看startLocked函数,它在SensorThread中,
void startLocked(ISensorService service) {
try {
if (mThread == null) {
Bundle dataChannel = service.getDataChannel();
mThread = new Thread(new SensorThreadRunnable(dataChannel),
SensorThread.class.getName());
mThread.start();
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in startLocked: ", e);
}
}
第一次mThread为null,然后它调用了service.getDataChannel()函数,此函数在SensorService类中,主要调用了jni函数_sensors_control_open(),
public Bundle getDataChannel() throws RemoteException {
// synchronize so we do not require sensor HAL to be thread-safe.
synchronized(mListeners) {
return _sensors_control_open();
}
}
SensorService类中调用的jni函数主要都在com_android_server_SensorService.cpp文件 中,我们看一下这个函数
static jobject
android_open(JNIEnv *env, jclass clazz)
{
native_handle_t* handle = sSensorDevice->open_data_source(sSensorDevice);
if (!handle) {
return NULL;
}
// new Bundle()
jobject bundle = env->NewObject(
gBundleOffsets.mClass,
gBundleOffsets.mConstructor);
if (handle->numFds > 0) {
jobjectArray fdArray = env->NewObjectArray(handle->numFds,
gParcelFileDescriptorOffsets.mClass, NULL);
for (int i = 0; i < handle->numFds; i++) {
// new FileDescriptor()
jobject fd = env->NewObject(gFileDescriptorOffsets.mClass,
gFileDescriptorOffsets.mConstructor);
env->SetIntField(fd, gFileDescriptorOffsets.mDescriptor, handle->data[i]);
// new ParcelFileDescriptor()
jobject pfd = env->NewObject(gParcelFileDescriptorOffsets.mClass,
gParcelFileDescriptorOffsets.mConstructor, fd);
env->SetObjectArrayElement(fdArray, i, pfd);
}
// bundle.putParcelableArray("fds", fdArray);
env->CallVoidMethod(bundle, gBundleOffsets.mPutParcelableArray,
env->NewStringUTF("fds"), fdArray);
}
if (handle->numInts > 0) {
jintArray intArray = env->NewIntArray(handle->numInts);
env->SetIntArrayRegion(intArray, 0, handle->numInts, &handle->data[handle->numInts]);
// bundle.putIntArray("ints", intArray);
env->CallVoidMethod(bundle, gBundleOffsets.mPutIntArray,
env->NewStringUTF("ints"), intArray);
}
// delete the file handle, but don't close any file descriptors
native_handle_delete(handle);
return bundle;
}
它主要调用了HAL层的open_data_source()函数。取得一些文件描述符等信息。
接下来SensorThread创建一个线程,调用start()就进入SensorThreadRunnable类的run()函数了,所以我们接着去看run()函数,它首先调用open()函数
if (!open()) {
return;
}
在open()函数中调用了 jni函数sensors_data_open(fds, ints);
static jint
sensors_data_open(JNIEnv *env, jclass clazz, jobjectArray fdArray, jintArray intArray)
{
jclass FileDescriptor = env->FindClass("java/io/FileDescriptor");
jfieldID fieldOffset = env->GetFieldID(FileDescriptor, "descriptor", "I");
int numFds = (fdArray ? env->GetArrayLength(fdArray) : 0);
int numInts = (intArray ? env->GetArrayLength(intArray) : 0);
native_handle_t* handle = native_handle_create(numFds, numInts);
int offset = 0;
for (int i = 0; i < numFds; i++) {
jobject fdo = env->GetObjectArrayElement(fdArray, i);
if (fdo) {
handle->data[offset++] = env->GetIntField(fdo, fieldOffset);
} else {
handle->data[offset++] = -1;
}
}
if (numInts > 0) {
jint* ints = env->GetIntArrayElements(intArray, 0);
for (int i = 0; i < numInts; i++) {
handle->data[offset++] = ints[i];
}
env->ReleaseIntArrayElements(intArray, ints, 0);
}
// doesn't take ownership of the native handle
return sSensorDevice->data_open(sSensorDevice, handle);
}
这函数最终调用了HAL层的data_open(),之后run()函数就进入一个while循环了。
while (true) {
// wait for an event
final int sensor = sensors_data_poll(values, status, timestamp);
int accuracy = status[0];
synchronized (sListeners) {
if (sensor == -1 || sListeners.isEmpty()) {
if (sensor == -1) {
// we lost the connection to the event stream. this happens
// when the last listener is removed.
Log.d(TAG, "_sensors_data_poll() failed, we bail out.");
}
// we have no more listeners or polling failed, terminate the thread
sensors_data_close();
mThread = null;
break;
}
final Sensor sensorObject = sHandleToSensor.get(sensor);
if (sensorObject != null) {
// report the sensor event to all listeners that
// care about it.
final int size = sListeners.size();
for (int i=0 ; i<size ; i++) {
ListenerDelegate listener = sListeners.get(i);
if (listener.hasSensor(sensorObject)) {
// this is asynchronous (okay to call
// with sListeners lock held).
listener.onSensorChangedLocked(sensorObject,
values, timestamp, accuracy);
}
}
}
}
它调用了jni函数sensors_data_poll()一直读数据。
static jint
sensors_data_poll(JNIEnv *env, jclass clazz,
jfloatArray values, jintArray status, jlongArray timestamp)
{
sensors_data_t data;
int res = sSensorDevice->poll(sSensorDevice, &data);
if (res >= 0) {
jint accuracy = data.vector.status;
env->SetFloatArrayRegion(values, 0, 3, data.vector.v);
env->SetIntArrayRegion(status, 0, 1, &accuracy);
env->SetLongArrayRegion(timestamp, 0, 1, &data.time);
}
return res;
}
把传感器得到的值都放在value数组中,根据返回的传感器标志sensor,把它分派给在sListener列表中所有的listener,如果listener中有监听这个sensor,就把它分派给这个listener,此时就会引起onSensorChange()了。
好了,获取传感器数据主要是这样一个途径。最后我们去分析一下unregisterListener()函数。
private void unregisterListener(Object listener) {
if (listener == null) {
return;
}
try {
synchronized (sListeners) {
final int size = sListeners.size();
for (int i=0 ; i<size ; i++) {
ListenerDelegate l = sListeners.get(i);
if (l.getListener() == listener) {
// disable all sensors for this listener
for (Sensor sensor : l.getSensors()) {
String name = sensor.getName();
int handle = sensor.getHandle();
mSensorService.enableSensor(l, name, handle, SENSOR_DISABLE);
}
sListeners.remove(i);
break;
}
}
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in unregisterListener: ", e);
}
}
不用想这个函数会做一些与registerListener相反的事情,至少差不多。它先在sListeners列表中找到这个listener,然后先调用enableSensor()函数禁止这个传感器。我们跟踪一下这函数,在SensorService类中。
synchronized(mListeners) {
if (enable!=SENSOR_DISABLE && !_sensors_control_activate(sensor, true)) {
Log.w(TAG, "could not enable sensor " + sensor);
return false;
}
Listener l = null;
int minDelay = enable;
for (Listener listener : mListeners) {
if (binder == listener.mToken) {
l = listener;
}
if (minDelay > listener.mDelay)
minDelay = listener.mDelay;
}
if (l == null && enable!=SENSOR_DISABLE) {
l = new Listener(binder);
binder.linkToDeath(l, 0);
mListeners.add(l);
mListeners.notify();
}
if (l == null) {
// by construction, this means we're disabling a listener we
// don't know about...
Log.w(TAG, "listener with binder " + binder +
", doesn't exist (sensor=" + name + ", id=" + sensor + ")");
return false;
}
if (minDelay >= 0) {
_sensors_control_set_delay(minDelay);
}
if (enable != SENSOR_DISABLE) {
l.addSensor(sensor, enable);
} else {
l.removeSensor(sensor);
deactivateIfUnusedLocked(sensor);
if (l.mSensors == 0) {
mListeners.remove(l);
binder.unlinkToDeath(l, 0);
mListeners.notify();
}
}
if (mListeners.size() == 0) {
_sensors_control_wake();
_sensors_control_close();
}
}
return true;
你们看到它的实现了吧。如果enable是true的话,就调用_sensors_control_activate(),如果是false的话,就调用deactivateIfUnusedLocked(),它们最终都会调用 HAL层的active()函数。最后,如果是禁止传感器的话,如果mListeners为空了,它就会调用
_sensors_control_wake();
_sensors_control_close();
这两个jni函数,最终会调用HAL层的wake()和close_data_source()函数。当调用wake()函数时,会使SensorManager类线程的run()函数中的sensor_data_poll()函数立即返回,此时在run()函数中调用sensors_data_close();最终会调用HAL层的data_close()函数。至此,一个传感器从初始到结束的流程就分析完了。
所以在java使用一个传感器在HAL层具体调用的函数流程为:
首先,sensors_control_open(),只在系统初始化时调用一次。用来初始化control_device结构体。
以下的是每次使用传感器一般经过的流程,注意,是一般而已,有些并不执行
(1)sensors_data_open
(2)get_sensors_list
(3)activate
(4)set_delay
(5)open_data_source
(6)data_open
(7)poll
一直读数据。。。。。。。。。。。
退出时
(8)activate
(9)sensors_control_close
(10)data_close
原文:http://blog.csdn.net/JerryMo06/archive/2010/04/15/5487476.aspx
发表评论
-
eclipse中安装插件地址
2014-03-07 15:08 755http://subclipse.tigris.org/up ... -
ubuntu13下载android源码
2014-02-27 18:23 632一、注意repo的正确地址 repo:curl " ... -
用例无法运行,报如下错:Exception during suite construction
2014-02-26 15:47 1264一 前提 1、 测试工程中的所有参数已配置好,如ins ... -
dx.jar dx.bat
2013-06-17 19:33 2255Android SDK中dx.jar, dx.bat文件的备份 ... -
Please ensure that adb is correctly located..... 问题
2013-04-16 09:44 963解决方法: 方法一、查毒杀毒,也许了病毒占用了adb ... -
PC端通过adb与设备端通信
2013-03-28 09:36 1509adb 全称Android Debug Bri ... -
Unable to execute dex: Multiple dex files define Lorg/taptwo/android/widget/Circ
2013-02-21 15:07 2575问题:[2013-02-21 15:01:02 - Dex ... -
android viewTree and decorView
2013-01-30 13:55 1694Android ViewTree and DecorView ... -
No active compatible AVD's or devices found. Relaunch this configuration after c
2013-01-29 10:56 8759问题:No active compatible AVD's ... -
代码对比工具
2013-01-24 15:33 646windows: http://www.scooterso ... -
android最新源码下载
2013-01-23 09:57 1048源码下载:https://source.android.co ... -
Run MonkeyTalk Scripts via Ant in Windows
2012-12-18 20:24 1276Run MonkeyTalk Scripts via ... -
Android中cpu,memory,Battery的计算
2012-11-20 19:59 66101 Memory的分配(RAM而非ROM) 网址: •ht ... -
http://code.taobao.org/p/TMTS/src/
2012-10-12 17:38 1029http://code.taobao.org/p/TMTS/s ... -
string.xml文件中的特殊符号转换符
2012-09-24 09:09 776strings.xml文件中需要对特殊符号(如%,'等)进行转 ... -
web server 中设置wifi代理
2012-09-24 09:07 893DefaultHttpClient httpClient = ... -
Android开发一些常见问题
2012-09-24 09:06 7411:当追踪问题时,代码中实在找不出问题所以,代码的逻辑完全正确 ... -
将log信息写入sdcard
2012-07-05 17:14 869File mFile; private void write ... -
string.xml文件中的特殊符号转换符
2012-06-19 19:39 1049strings.xml文件中需要对特殊符号(如%,'等)进行转 ... -
关于popupWindow的dismiss
2012-06-17 16:13 8585View contentView = LayoutInflat ...
相关推荐
1. **传感器(Sensors)**:在Android中,指南针主要依赖磁力传感器(Magnetic Sensor)和加速度传感器(Accelerometer)来获取设备的方位信息。通过调用`SensorManager`类获取这两个传感器的数据,然后利用`...
2. **传感器(Sensors)**:Android设备通常包含多种传感器,如磁力计(Magnetic Field Sensor),它是实现指南针功能的关键。磁力计能检测到地球的磁场强度,从而计算出设备的磁场角度,进而转化为方向信息。 3. **...
2. 传感器管理:在`android/hardware/sensors`或`android/hardware/interfaces`中,可以找到关于如何接入和处理传感器数据的代码,这对于健康和运动相关的应用至关重要。 3. 连接管理:`android/wearable/service`...
"安卓Android源码——PM25.zip"很可能是一个包含了与空气质量监测相关的应用或服务的源代码库,尤其是针对PM2.5颗粒物的监测。PM2.5是指空气中直径小于或等于2.5微米的颗粒物,它们对环境和人体健康有较大影响。下面...
《精通Android4源码》是一本深入探讨Android4系统源码及开发实践的专业书籍,其提供的源码资源是开发者进一步理解和应用Android平台的关键。通过分析这些源码,开发者可以掌握更多的高级特性和优化技巧,从而提升...
本资源"Android重力传感器源码.zip"包含的是Android操作系统中处理重力传感器数据的相关源代码,这对于理解Android系统如何与硬件交互以及如何解析传感器数据非常有帮助。 首先,我们需要了解Android的Sensor框架。...
总结来说,实现Android 吹一吹效果源码涉及到Android的传感器API、音频处理、UI动画、权限管理等多个方面。开发者需要对Android系统有深入理解,并具备一定的算法基础,才能有效实现这一独特的交互功能。
本项目“Android简单计步器源码”提供了一个基础的实现,可以帮助开发者理解和学习如何利用Android SDK中的健康与健身相关的API来实现计步功能。 首先,Android计步器的核心在于使用加速度传感器(Accelerometer)...
1. **传感器(Sensors)**:Android系统提供了丰富的传感器接口,包括加速度计(Accelerometer)、陀螺仪(Gyroscope)和地磁传感器(Magnetic Field Sensor),这些传感器在指南针应用中起到核心作用。指南针的基本原理是...
在Android源码中,姿态传感器的相关实现位于`frameworks/base/core/java/android/hardware/Sensor.java`和`硬件/libhardware/include/hardware/sensors.h`等位置。`Sensor.java`包含了Android系统对传感器接口的定义...
"安卓Android源码——thermometer_android仪表盘.zip" 是一个与安卓应用开发相关的项目,其中包含了名为 "thermometer_android" 的源码,此项目可能是一个模拟温度计功能的应用。"thermometer" 通常指的是温度计,而...
下面将详细讲解基于Android的计步器源码中的关键知识点。 1. **传感器(Sensor)API**: Android系统提供了Sensor API,允许开发者访问设备的各种传感器,如加速度计,用于检测设备的运动状态。计步器功能主要依赖...
这个源码实例将深入解析如何在Android应用程序中利用重力传感器的数据,实现对用户设备运动状态的检测。 在Android系统中,重力传感器的API主要位于`android.hardware.Sensor`和`android.hardware.SensorEvent`类中...
1. **传感器(Sensors)**:Android系统提供了丰富的传感器接口,指南针应用主要依赖于地磁传感器(Magnetic Field Sensor)和加速度传感器(Accelerometer)。这两个传感器结合使用,可以计算出设备相对于地球磁场...
这份压缩包"Android程序研发源码Android 指南针程序.zip"包含了实现这样一个功能的完整源代码。以下是对这个指南针程序的关键知识点的详细解释。 1. **传感器(Sensors)** Android系统提供了一个强大的传感器框架,...
1. **传感器(Sensors)**:Android指南针的核心是地磁传感器(Magnetic Field Sensor),它能够检测设备周围的磁场强度,提供X、Y、Z三个轴上的数据。另一个重要传感器是陀螺仪(Gyroscope),用于检测设备的旋转运动。...
例如,访问传感器需要`<uses-permission android:name="android.permission.BODY_SENSORS" />`。同时,对于Android 6.0(API级别23)及以上版本,可能还需要在运行时请求权限。 6. **服务和服务绑定** 为了在后台...
这份"安卓Android源码——指南针定位源码.zip"压缩包提供了实现指南针功能的源代码,对于学习和理解如何在Android应用中集成指南针定位功能非常有帮助。下面我们将深入探讨这个主题,详细介绍相关知识点。 1. **...
访问传感器数据需要在AndroidManifest.xml中声明相应的权限,如`<uses-permission android:name="android.permission.BODY_SENSORS" />`。 7. **UI响应**: 用户可能能够点击或滑动仪表盘进行交互,这就需要处理...
在Android平台上,"摇一摇"功能是一种常见的用户交互方式,常常用于实现各种有趣的互动体验,比如游戏、...通过学习和分析这个源码,开发者可以更好地理解和掌握Android中的传感器使用以及如何实现这种动态交互效果。