第一节我们分析到应用调用SensorManager最后是调用了SystemSensorManager中,但是其是SensorManager的子类,因此可以调用父类的接口最后到子类的实现中,我们先看下其构造函数:

一、SystemSensorManager的初始化


    public SystemSensorManager(Context context, Looper mainLooper) {        mMainLooper = mainLooper;//这边的mainLooper是应用主线程的looper        mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;        synchronized(sSensorModuleLock) {            if (!sSensorModuleInitialized) {                sSensorModuleInitialized = true;                nativeClassInit();//native方法                // initialize the sensor list                final ArrayList fullList = sFullSensorsList;//sFullSensorsList是一个静态变量,保存所有的sensor                int i = 0;                do {                    Sensor sensor = new Sensor();//新建一个sensor                    i = nativeGetNextSensor(sensor, i);//传到JNI层,把sensor的信息补全                    if (i>=0) {                        //Log.d(TAG, "found sensor: " + sensor.getName() +                        //        ", handle=" + sensor.getHandle());                        fullList.add(sensor);                        sHandleToSensor.append(sensor.getHandle(), sensor);                    }                } while (i>0);            }        }    }

我们先来看下nativeClassInit方法,这个方法是在文件android_hardware_SensorManager.cpp文件中

static voidnativeClassInit (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");    sensorOffsets.minDelay    = _env->GetFieldID(sensorClass, "mMinDelay",  "I");    sensorOffsets.fifoReservedEventCount =            _env->GetFieldID(sensorClass, "mFifoReservedEventCount",  "I");    sensorOffsets.fifoMaxEventCount = _env->GetFieldID(sensorClass, "mFifoMaxEventCount",  "I");    sensorOffsets.stringType = _env->GetFieldID(sensorClass, "mStringType", "Ljava/lang/String;");    sensorOffsets.requiredPermission = _env->GetFieldID(sensorClass, "mRequiredPermission",                                                        "Ljava/lang/String;");    sensorOffsets.maxDelay    = _env->GetFieldID(sensorClass, "mMaxDelay",  "I");    sensorOffsets.flags = _env->GetFieldID(sensorClass, "mFlags",  "I");}

我们看这个方法,其主要是找到java层Sensor这个类的成员变量的FileId而已。

再来看看nativeGetNextSensor方法

static jintnativeGetNextSensor(JNIEnv *env, jclass clazz, jobject sensor, jint next){    SensorManager& mgr(SensorManager::getInstance());    Sensor const* const* sensorList;    size_t count = mgr.getSensorList(&sensorList);//获取到sensor的列表    if (size_t(next) >= count)        return -1;    Sensor const* const list = sensorList[next];    const SensorOffsets& sensorOffsets(gSensorOffsets);    jstring name = env->NewStringUTF(list->getName().string());    jstring vendor = env->NewStringUTF(list->getVendor().string());    jstring stringType = env->NewStringUTF(list->getStringType().string());    jstring requiredPermission = env->NewStringUTF(list->getRequiredPermission().string());    env->SetObjectField(sensor, sensorOffsets.name,      name);    env->SetObjectField(sensor, sensorOffsets.vendor,    vendor);    env->SetIntField(sensor, sensorOffsets.version,      list->getVersion());    env->SetIntField(sensor, sensorOffsets.handle,       list->getHandle());    env->SetIntField(sensor, sensorOffsets.type,         list->getType());    env->SetFloatField(sensor, sensorOffsets.range,      list->getMaxValue());    env->SetFloatField(sensor, sensorOffsets.resolution, list->getResolution());    env->SetFloatField(sensor, sensorOffsets.power,      list->getPowerUsage());    env->SetIntField(sensor, sensorOffsets.minDelay,     list->getMinDelay());    env->SetIntField(sensor, sensorOffsets.fifoReservedEventCount,                     list->getFifoReservedEventCount());    env->SetIntField(sensor, sensorOffsets.fifoMaxEventCount,                     list->getFifoMaxEventCount());    env->SetObjectField(sensor, sensorOffsets.stringType, stringType);    env->SetObjectField(sensor, sensorOffsets.requiredPermission,                        requiredPermission);    env->SetIntField(sensor, sensorOffsets.maxDelay, list->getMaxDelay());    env->SetIntField(sensor, sensorOffsets.flags, list->getFlags());    next++;    return size_t(next) < count ? next : 0;}

上面的函数获取到sensormanager.cpp的sensor列表,然后把上层传下来的sensor信息补全。

我们来看下SensorManager::getSensorList函数:

ssize_t SensorManager::getSensorList(Sensor const* const** list) const{    Mutex::Autolock _l(mLock);    status_t err = assertStateLocked();    if (err < 0) {        return ssize_t(err);    }    *list = mSensorList;    return mSensors.size();}
其将mSensorList返回,而这个对象在assertStateLocked函数中赋值,assertStateLocked函数又是在SensorManager的构造函数中直接调用

status_t SensorManager::assertStateLocked() const {    if (mSensorServer == NULL) {        // try for one second        const String16 name("sensorservice");        for (int i=0 ; i<4 ; i++) {            status_t err = getService(name, &mSensorServer);            if (err == NAME_NOT_FOUND) {                usleep(250000);                continue;            }            if (err != NO_ERROR) {                return err;            }            break;        }        class DeathObserver : public IBinder::DeathRecipient {            SensorManager& mSensorManger;            virtual void binderDied(const wp& who) {                ALOGW("sensorservice died [%p]", who.unsafe_get());                mSensorManger.sensorManagerDied();            }        public:            DeathObserver(SensorManager& mgr) : mSensorManger(mgr) { }        };        mDeathObserver = new DeathObserver(*const_cast(this));        mSensorServer->asBinder()->linkToDeath(mDeathObserver);        mSensors = mSensorServer->getSensorList();//调用了SensorService的getSensorList方法        size_t count = mSensors.size();        mSensorList = (Sensor const**)malloc(count * sizeof(Sensor*));        for (size_t i=0 ; i

最后是调用了SensorService的getSensorList方法

Vector SensorService::getSensorList(){    char value[PROPERTY_VALUE_MAX];    property_get("debug.sensors", value, "0");    const Vector& initialSensorList = (atoi(value)) ?            mUserSensorListDebug : mUserSensorList;    Vector accessibleSensorList;    for (size_t i = 0; i < initialSensorList.size(); i++) {        Sensor sensor = initialSensorList[i];        if (canAccessSensor(sensor)) {            accessibleSensorList.add(sensor);        } else {            String8 infoMessage;            infoMessage.appendFormat(                    "Skipped sensor %s because it requires permission %s",                    sensor.getName().string(),                    sensor.getRequiredPermission().string());            ALOGI(infoMessage.string());        }    }    return accessibleSensorList;}

getSensorList中主要是将mUserSensorListDebug , mUserSensorList中的sensor拿出来返回

这两个列表主要在onFirstRef中添加,这个函数在对象实例化的时候就调用了。

void SensorService::onFirstRef() {....... mUserSensorList = mSensorList;            if (hasGyro) {                Sensor aSensor;                // Add Android virtual sensors if they're not already                // available in the HAL                aSensor = registerVirtualSensor( new RotationVectorSensor() );                if (virtualSensorsNeeds & (1<

这样就把上层传下来的sensor的信息补全了,最后SystemSensorManager把所有的sensor信息保存起来。


二、SystemSensorManager的注册Listener

接下来就是调用registerListener来注册监听了,最终会调用到SystemSensorManager中的registerListenerImpl接口。

    /** @hide */    @Override    protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,            int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {        if (listener == null || sensor == null) {            Log.e(TAG, "sensor or listener is null");            return false;        }        // Trigger Sensors should use the requestTriggerSensor call.        if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {            Log.e(TAG, "Trigger Sensors should use the requestTriggerSensor.");            return false;        }        if (maxBatchReportLatencyUs < 0 || delayUs < 0) {            Log.e(TAG, "maxBatchReportLatencyUs and delayUs should be non-negative");            return false;        }        // Invariants to preserve:        // - one Looper per SensorEventListener        // - one Looper per SensorEventQueue        // We map SensorEventListener to a SensorEventQueue, which holds the looper        synchronized (mSensorListeners) {            SensorEventQueue queue = mSensorListeners.get(listener);            if (queue == null) {                Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;                queue = new SensorEventQueue(listener, looper, this);//新建SensorEventQueue                if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs, reservedFlags)) {                    queue.dispose();                    return false;                }                mSensorListeners.put(listener, queue);                return true;            } else {                return queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs, reservedFlags);            }        }    }

先去从mSensorListeners中查找listenr的SensorEventQueue,没有新建一个,有的话加入注册的sensor。我们先来看下SensorEventQueue的构造函数:

    static final class SensorEventQueue extends BaseEventQueue {        private final SensorEventListener mListener;        private final SparseArray mSensorsEvents = new SparseArray();        public SensorEventQueue(SensorEventListener listener, Looper looper,                SystemSensorManager manager) {            super(looper, manager);            mListener = listener;        }

其构造函数没有什么特别的,再来看下其父类的BaseEventQueue 的构造函数:

        BaseEventQueue(Looper looper, SystemSensorManager manager) {            nSensorEventQueue = nativeInitBaseEventQueue(this, looper.getQueue(), mScratch);            mCloseGuard.open("dispose");            mManager = manager;        }

其调用了nativeInitBaseEventQueue的jni函数:

static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jobject eventQ, jobject msgQ, jfloatArray scratch) {    SensorManager& mgr(SensorManager::getInstance());    sp queue(mgr.createEventQueue());//在SensorManager中建一个SensorEventQueue    sp messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);    if (messageQueue == NULL) {        jniThrowRuntimeException(env, "MessageQueue is not initialized.");        return 0;    }    sp receiver = new Receiver(queue, messageQueue, eventQ, scratch);//新建一个Receiver    receiver->incStrong((void*)nativeInitSensorEventQueue);    return jlong(receiver.get());}

新建一个Receiver,传入一个SensorEventQueue和MessageQueue,MessageQueue是上层传下来的。


三、Receiver将应用fd加入looper

我们再来看看Receiver的构造函数:

    Receiver(const sp& sensorQueue,            const sp& messageQueue,            jobject receiverObject, jfloatArray scratch) {        JNIEnv* env = AndroidRuntime::getJNIEnv();        mSensorQueue = sensorQueue;        mMessageQueue = messageQueue;        mReceiverObject = env->NewGlobalRef(receiverObject);        mScratch = (jfloatArray)env->NewGlobalRef(scratch);    }

再来看看onFirstRef函数,是将上层传下来的MessageQueue中的looper加入了SensorEventQueue的fd,并且Receiver这个类是继承了public LooperCallback,也就是它实现了handleEvent函数,来实现looper中的epoll的回调,这个具体在按键流程中详细介绍过,这里就不再左介绍了。

    virtual void onFirstRef() {        LooperCallback::onFirstRef();        mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0,                ALOOPER_EVENT_INPUT, this, mSensorQueue.get());    }

那我们再来看看SensorEventQueue的创建,是调用了SensorManager的createEventQueue方法:

sp SensorManager::createEventQueue(){    sp queue;    Mutex::Autolock _l(mLock);    while (assertStateLocked() == NO_ERROR) {        sp connection =                mSensorServer->createSensorEventConnection();//调用了SensorService的createSensorEventConnection        if (connection == NULL) {            // SensorService just died.            ALOGE("createEventQueue: connection is NULL. SensorService died.");            continue;        }        queue = new SensorEventQueue(connection);        break;    }    return queue;}

这个函数中调用了SensorService的createSensorEventConnection方法返回一个Connection,然后作为入参构造了SensorEventQueue对象,

先来看下SensorEventQueue对象

SensorEventQueue::SensorEventQueue(const sp& connection)    : mSensorEventConnection(connection), mRecBuffer(NULL), mAvailable(0), mConsumed(0),      mNumAcksToSend(0) {    mRecBuffer = new ASensorEvent[MAX_RECEIVE_BUFFER_EVENT_COUNT];}SensorEventQueue::~SensorEventQueue() {    delete [] mRecBuffer;}void SensorEventQueue::onFirstRef(){    mSensorChannel = mSensorEventConnection->getSensorChannel();}int SensorEventQueue::getFd() const{    return mSensorChannel->getFd();}

最后还是调了connection才能调用到getFd。我们来看下SensorService的createSensorEventConnection函数返回的connection

sp SensorService::createSensorEventConnection(){    uid_t uid = IPCThreadState::self()->getCallingUid();    sp result(new SensorEventConnection(this, uid));    return result;}

再来看SensorEventConnection的构造函数,其mChannel的一个BitTube对象

SensorService::SensorEventConnection::SensorEventConnection(        const sp& service, uid_t uid)    : mService(service), mUid(uid), mWakeLockRefCount(0), mHasLooperCallbacks(false),      mDead(false), mEventCache(NULL), mCacheSize(0), mMaxCacheSize(0) {    mChannel = new BitTube(mService->mSocketBufferSize);#if DEBUG_CONNECTIONS    mEventsReceived = mEventsSentFromCache = mEventsSent = 0;    mTotalAcksNeeded = mTotalAcksReceived = 0;#endif}

我们再看BitTube对象

BitTube::BitTube()    : mSendFd(-1), mReceiveFd(-1){    init(DEFAULT_SOCKET_BUFFER_SIZE, DEFAULT_SOCKET_BUFFER_SIZE);}BitTube::BitTube(size_t bufsize)    : mSendFd(-1), mReceiveFd(-1){    init(bufsize, bufsize);}BitTube::BitTube(const Parcel& data)    : mSendFd(-1), mReceiveFd(-1){    mReceiveFd = dup(data.readFileDescriptor());    if (mReceiveFd < 0) {        mReceiveFd = -errno;        ALOGE("BitTube(Parcel): can't dup filedescriptor (%s)",                strerror(-mReceiveFd));    }}BitTube::~BitTube(){    if (mSendFd >= 0)        close(mSendFd);    if (mReceiveFd >= 0)        close(mReceiveFd);}void BitTube::init(size_t rcvbuf, size_t sndbuf) {    int sockets[2];    if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {        size_t size = DEFAULT_SOCKET_BUFFER_SIZE;        setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));        setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));        // sine we don't use the "return channel", we keep it small...        setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));        setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));        fcntl(sockets[0], F_SETFL, O_NONBLOCK);        fcntl(sockets[1], F_SETFL, O_NONBLOCK);        mReceiveFd = sockets[0];        mSendFd = sockets[1];    } else {        mReceiveFd = -errno;        ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd));    }}

我们看到在init中创建一个一对socketpair,一个给mReceiveFd,另一个给mSendFd。和按键流程很像吧。

getFd返回就是mReceiveFd

int BitTube::getFd() const{    return mReceiveFd;}

这样就很清晰了,SensorService中有sensor数据到来的时候,发送数据的时候利用上面的sendFd来发送数据,这样mReceiveFd就有数据,这样Looper的epoll就唤醒,调用了注册的回调handEvent函数,然后再到上层。但有没有觉得很奇怪,SensorService没有保存sendFd。我们来看刚那个函数:

sp SensorService::createSensorEventConnection(){    uid_t uid = IPCThreadState::self()->getCallingUid();    sp result(new SensorEventConnection(this, uid));    return result;}

这个后面详细再说。


四、Receiver的回调

我们再来看看Receiver的回调handleEvent函数

    virtual int handleEvent(int fd, int events, void* data) {        JNIEnv* env = AndroidRuntime::getJNIEnv();        sp q = reinterpret_cast(data);        ssize_t n;        ASensorEvent buffer[16];        while ((n = q->read(buffer, 16)) > 0) {            for (int i=0 ; iSetFloatArrayRegion(mScratch, 0, 1, &value);                } else {                    env->SetFloatArrayRegion(mScratch, 0, 16, buffer[i].data);                }                if (buffer[i].type == SENSOR_TYPE_META_DATA) {                    // This is a flush complete sensor event. Call dispatchFlushCompleteEvent                    // method.                    env->CallVoidMethod(mReceiverObject,                                        gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,                                        buffer[i].meta_data.sensor);                } else {                    int8_t status;                    switch (buffer[i].type) {                    case SENSOR_TYPE_ORIENTATION:                    case SENSOR_TYPE_MAGNETIC_FIELD:                    case SENSOR_TYPE_ACCELEROMETER:                    case SENSOR_TYPE_GYROSCOPE:                        status = buffer[i].vector.status;                        break;                    case SENSOR_TYPE_HEART_RATE:                        status = buffer[i].heart_rate.status;                        break;                    default:                        status = SENSOR_STATUS_ACCURACY_HIGH;                        break;                    }                    env->CallVoidMethod(mReceiverObject,                                        gBaseEventQueueClassInfo.dispatchSensorEvent,                                        buffer[i].sensor,                                        mScratch,                                        status,                                        buffer[i].timestamp);                }                if (env->ExceptionCheck()) {                    mSensorQueue->sendAck(buffer, n);                    ALOGE("Exception dispatching input event.");                    return 1;                }            }            mSensorQueue->sendAck(buffer, n);//给SensorService返回信息        }        if (n<0 && n != -EAGAIN) {            // FIXME: error receiving events, what to do in this case?        }        return 1;    }

当有数据过来的时候调用上面的java层的dispatchSensorEvent函数,最后sendAck返回信息给SensorService,也是SensorEventQueue中的mReceiveFd发送。

我们再来看看java层的dispatchSensorEvent函数:

        protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,                long timestamp) {            final Sensor sensor = sHandleToSensor.get(handle);            SensorEvent t = null;            synchronized (mSensorsEvents) {                t = mSensorsEvents.get(handle);            }            if (t == null) {                // This may happen if the client has unregistered and there are pending events in                // the queue waiting to be delivered. Ignore.                return;            }            // 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 changes            final 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);        }

最后将数据传给应用的onSensorChanged方法。在传给应用之前,我们将数据封装成了SensorEvent,在每一个EventQueue addSensor的时候会调用addSensorEvent函数 

        public void addSensorEvent(Sensor sensor) {            SensorEvent t = new SensorEvent(Sensor.getMaxLengthValuesArray(sensor,                    mManager.mTargetSdkLevel));            synchronized (mSensorsEvents) {                mSensorsEvents.put(sensor.getHandle(), t);            }        }

最后封装SensorEvent,也从mSensorsEvents中取出来,再赋值。


五、使能Sensor

最后一个问题,是SensorService中还没有sendFd的保存,下面我们看看何时把这个fd保存在SensorService的呢?

我们先来看下BaseEventQueue的addSensor函数

        public boolean addSensor(                Sensor sensor, int delayUs, int maxBatchReportLatencyUs, int reservedFlags) {            // 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);//加入ActiveSensor的列表中去            addSensorEvent(sensor);//加入            if (enableSensor(sensor, delayUs, maxBatchReportLatencyUs, reservedFlags) != 0) {//调用enableSensor                // Try continuous mode if batching fails.                if (maxBatchReportLatencyUs == 0 ||                    maxBatchReportLatencyUs > 0 && enableSensor(sensor, delayUs, 0, 0) != 0) {                  removeSensor(sensor, false);                  return false;                }            }            return true;        }

我们再来看看enableSensor函数

        private int enableSensor(                Sensor sensor, int rateUs, int maxBatchReportLatencyUs, int reservedFlags) {            if (nSensorEventQueue == 0) throw new NullPointerException();            if (sensor == null) throw new NullPointerException();            return nativeEnableSensor(nSensorEventQueue, sensor.getHandle(), rateUs,                    maxBatchReportLatencyUs, reservedFlags);        }

这个函数中又调用了nativeEnableSensor函数:

static jint nativeEnableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle, jint rate_us,                               jint maxBatchReportLatency, jint reservedFlags) {    sp receiver(reinterpret_cast(eventQ));    return receiver->getSensorEventQueue()->enableSensor(handle, rate_us, maxBatchReportLatency,                                                         reservedFlags);}

我们再来看看SensorEventQueue的enableSensor函数

status_t SensorEventQueue::enableSensor(int32_t handle, int32_t samplingPeriodUs,                                        int maxBatchReportLatencyUs, int reservedFlags) const {    return mSensorEventConnection->enableDisable(handle, true, us2ns(samplingPeriodUs),                                                 us2ns(maxBatchReportLatencyUs), reservedFlags);}

来看看connection的enableDisable函数:

status_t SensorService::SensorEventConnection::enableDisable(        int handle, bool enabled, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs,        int reservedFlags){    status_t err;    if (enabled) {        err = mService->enable(this, handle, samplingPeriodNs, maxBatchReportLatencyNs,                               reservedFlags);    } else {        err = mService->disable(this, handle);    }    return err;}

又调用了SensorService的enable函数,将Connection加入mActiveConnections

status_t SensorService::enable(const sp& connection,        int handle, nsecs_t samplingPeriodNs,  nsecs_t maxBatchReportLatencyNs, int reservedFlags){.......    if (connection->addSensor(handle)) {        BatteryService::enableSensor(connection->getUid(), handle);        // the sensor was added (which means it wasn't already there)        // so, see if this connection becomes active        if (mActiveConnections.indexOf(connection) < 0) {            mActiveConnections.add(connection);        }    }.....}

而在SensorService中会在threadLoop函数中调用下面来发送数据,而下面的activeConnections就是从mActiveConnections获取的。

        bool needsWakeLock = false;        size_t numConnections = activeConnections.size();        for (size_t i=0 ; i < numConnections; ++i) {            if (activeConnections[i] != 0) {                activeConnections[i]->sendEvents(mSensorEventBuffer, count, mSensorEventScratch,                        mMapFlushEventsToConnections);

最后SensorEventConnection也是调用了sendEvents,而这个函数是做了write sendFd这样的操作,然后应用进程的epoll机制唤醒,调用回调再到Receiver的handleEvent,然后再会反调Java的dispatchSensorEvent函数,最后就到应用的onSensorChanged里面了。


六|、总结

总结:这样我们就把sensor数据从SensorService到应用的onSensorChanged分析完了,至于SensorService如何获取各个sensor的数据,等等留作以后分析。



更多相关文章

  1. Android:Service:服务的生命周期
  2. Android——本地服务基础(一)
  3. 关于Android中Service的onDestory()调用时机
  4. Android(安卓)GestureDetector ScaleGestureDetector
  5. Linux下的两种timer方法 (Android(安卓)下NDK开发)
  6. Android中调用外部地图程序
  7. Android(安卓)怎么把异常的StackTrace信息格式化为String
  8. Android(安卓)一般动画Animation和属性动画Animator
  9. 三端易用的现代跨平台JsBridge之 IOS篇

随机推荐

  1. Android中三星调用系统相机拍照后旋转的
  2. Android(安卓)各版本代号 & Java Source
  3. android webview 遇到android.os.FileUri
  4. Android属性动画property animation
  5. Android开发者实用代码片段
  6. Android加速度传感器
  7. Android IDL 小例子
  8. [置顶] Android 系列:安装Android SDK出现
  9. Android解析XML
  10. 关于android创建对话框报错The method se