做Android开发的童鞋都玩过SensorEventListener去监听Sensor设备的数据包括加速度,陀螺仪,地磁,光感,距感
现在我们要玩的是用C++去封装动态库实现SensorEventListener
通过这篇文章你会深刻明白EventListner的本质是什么?
我先概括SensorEventListener本质是什么:Framework Nativie层有个SensorService去poll Sensor设备数据。app每次调用registerListener其实就是建立个Bittube管道实现进程通信,每次有数据来的时候就通过JNI调用onSensorChanged()回调通知APP
我这边只给出实现代码,具体的逻辑需要读者去参考我的博文http://blog.youkuaiyun.com/szqsdq/article/details/76855342 去理解Sensor Framework框架知识
核心代码如下
/*
*Created by Zhongqi.Shao on 2017/11/29.
*SDK合理的情况就是只有1个通道1个looper去轮询每次registerListener的时候更新listener地址
*/
#ifndef SENSORNATIVE_SENSORCLIENT_H
#define SENSORNATIVE_SENSORCLIENT_H
#include <gui/SensorManager.h>
#include <gui/Sensor.h>
#include <jni.h>
#include <JNIHelp.h>
#include <stdarg.h>
#include "NativeMessageQueue.h"
#define PACKAGE_NAME "SensorNative"
using namespace android;
class SensorClient:public RefBase{
private:
SensorManager* _sensorManager;
//packageName对应servicea的Key析构时自动清理connection
sp<SensorEventQueue> _sensorEventQueue;
Sensor const* const* _sensorList;
virtual void onFirstRef();
//receiver封装了轮询回调
long _nativeSensorReceiver;
public:
typedef void (*__sensor_callback)(void *pCtx, int type ,float* dataArray,long timeStamp);
typedef struct {
__sensor_callback cb;
float* dataArray;
void *ctx;
}sensor_call_back_obj;
SensorClient();
virtual ~SensorClient();
#ifdef PLATFORM_7420
SensorManager& getNativeSensorManager(const char* packageName);
#endif
//创建native层的messageQueue去轮询文件描述符 SDK层设置为1个通道每次registerListener的时候就去创建Looper去轮询
sp<MessageQueue> createNativeMessageQueue();
long createSensorReceiver();
//获得reveiver地址
long getSensorReceiverAddr();
//通过type获得senosr
Sensor const* getDefaultSensor(int type);
int nativeDisableSensor(long eventQ, int type);
int nativeEnableSensor( long eventQ, int type, int rate_us);
void destroyNativeReceiver(long eventQ);
void registerListener(void* callBackListener);
//receiver内部类
class SensorReceiver : public LooperCallback
{
private:
sp<SensorEventQueue> _mSensorQueue;
sp<MessageQueue> _mMessageQueue;
float* _mFloatArray;
sensor_call_back_obj* _mCallBackListener;
public:
SensorReceiver(const sp<SensorEventQueue>& sensorQueue,const sp<MessageQueue>& messageQueue)
{
_mSensorQueue = sensorQueue;
_mMessageQueue = messageQueue;
}
~SensorReceiver()
{
ALOGE("shao sensorreceiver xigou");
}
sp<SensorEventQueue> getSensorEventQueue() const
{
return _mSensorQueue;
}
void destroy()
{
_mMessageQueue->getLooper()->removeFd( _mSensorQueue->getFd() );
ALOGE("shao receiver destroy function");
}
void setCurrentListener(sensor_call_back_obj* callBackListener)
{
this->_mCallBackListener = callBackListener;
}
virtual void onFirstRef()
{
LooperCallback::onFirstRef();
_mMessageQueue->getLooper()->addFd(_mSensorQueue->getFd(), 0,ALOOPER_EVENT_INPUT, this, _mSensorQueue.get());
}
virtual int handleEvent(int fd, int events, void* data)
{
sp<SensorEventQueue> q = reinterpret_cast<SensorEventQueue *>(data);
//ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
ssize_t n;
ASensorEvent buffer[16];
while ((n = q->read(buffer, 16)) > 0) {
for (int i=0 ; i<n ; i++) {
//ALOGE("shao read size = %d\n",n);
if (buffer[i].type == SENSOR_TYPE_STEP_COUNTER) {
// step-counter returns a uint64, but the java API only deals with floats
float value = float(buffer[i].u64.step_counter);
memcpy(_mCallBackListener->dataArray, &value,sizeof(float) * 1);
} else {
memcpy(_mCallBackListener->dataArray, buffer[i].data,sizeof(float) * 16);
}
if (buffer[i].type == SENSOR_TYPE_META_DATA) {
} else {
int8_t status;
switch (buffer[i].type) {
case SENSOR_TYPE_ACCELEROMETER:
//ALOGE("shao accl type = %d, value0 = %7f,value1 = %7f,value2 = %7f\n",buffer[i].type,buffer[i].data[0],buffer[i].data[1],buffer[i].data[2]);
break;
case SENSOR_TYPE_GYROSCOPE:
//ALOGE("shao gyro type = %d,value0 = %7f,value1 = %7f,value2 = %7f\n",buffer[i].type,buffer[i].data[0],buffer[i].data[1],buffer[i].data[2]);
break;
case SENSOR_TYPE_MAGNETIC_FIELD:
//ALOGE("shao mag type = %d,value0 = %7f,value1 = %7f,value2 = %7f\n",buffer[i].type,buffer[i].data[0],buffer[i].data[1],buffer[i].data[2]);
break;
case SENSOR_TYPE_ORIENTATION:
case SENSOR_TYPE_GRAVITY:
case SENSOR_TYPE_LINEAR_ACCELERATION:
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;
}
if(_mCallBackListener != NULL)
{
_mCallBackListener->cb(_mCallBackListener->ctx , buffer[i].type,_mCallBackListener->dataArray, buffer[i].timestamp);
}
}
}
_mSensorQueue->sendAck(buffer, n);
}
if (n<0 && n != -EAGAIN) {
// FIXME: error receiving events, what to do in this case?
}
return 1;
}
};
};
#endif //SENSORNATIVE_SENSORCLIENT_H
//
// Created by Zhongqi.Shao on 2017/11/29.
//
#include "SensorClient.h"
#include <android_os_MessageQueue.h>
#include <android_runtime/AndroidRuntime.h>
SensorClient::SensorClient()
{
}
void SensorClient::onFirstRef()
{
ALOGD("shao first");
#ifdef PLATFORM_7420
_sensorManager = &getNativeSensorManager("SensorNative");
_sensorEventQueue = _sensorManager->createEventQueue(String8("SensorNative"));
#endif
#ifdef PLATFORM_3288
_sensorManager = new SensorManager();
_sensorEventQueue = _sensorManager->createEventQueue();
#endif
_nativeSensorReceiver = createSensorReceiver();
}
#ifdef PLATFORM_7420
SensorManager& SensorClient::getNativeSensorManager(const char* packageName)
{
return SensorManager::getInstanceForPackage(String16(packageName));
}
#endif
//创建native层的messageQueue
sp<MessageQueue> SensorClient::createNativeMessageQueue()
{
NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
if (!nativeMessageQueue)
{
ALOGE("Unable to allocate native queue");
return 0;
}
return reinterpret_cast<NativeMessageQueue*>(nativeMessageQueue);
}
//创建receiver里面拿到通道数据
long SensorClient::createSensorReceiver()
{
sp<SensorReceiver> receiver = new SensorReceiver(_sensorEventQueue, createNativeMessageQueue());
return reinterpret_cast<intptr_t>(receiver.get());
}
long SensorClient::getSensorReceiverAddr()
{
return _nativeSensorReceiver;
}
Sensor const* SensorClient::getDefaultSensor(int type)
{
return _sensorManager->getDefaultSensor(type);
}
void SensorClient::registerListener(void* callBackListener)
{
sensor_call_back_obj* callBack = reinterpret_cast<sensor_call_back_obj*>(callBackListener);
sp<SensorReceiver> receiver(reinterpret_cast<SensorReceiver *>(_nativeSensorReceiver));
receiver->setCurrentListener(callBack);
}
int SensorClient::nativeEnableSensor( long eventQ, int type, int rate_us)
{
Sensor const* tempSensor = getDefaultSensor(type);
if(tempSensor == NULL)
{
return -1;
}
int handle = tempSensor->getHandle();
ALOGE("shao native enable sensor type = %d\n",handle);
sp<SensorReceiver> receiver(reinterpret_cast<SensorReceiver *>(eventQ));
return receiver->getSensorEventQueue()->enableSensor(handle, rate_us, 0, 0);
}
int SensorClient::nativeDisableSensor(long eventQ, int type)
{
Sensor const* tempSensor = getDefaultSensor(type);
int handle = tempSensor->getHandle();
sp<SensorReceiver> receiver(reinterpret_cast<SensorReceiver *>(eventQ));
return receiver->getSensorEventQueue()->disableSensor(handle);
}
void SensorClient::destroyNativeReceiver(long eventQ)
{
sp<SensorReceiver> receiver(reinterpret_cast<SensorReceiver *>(eventQ));
if(receiver.get() != NULL)
{
receiver->destroy();
receiver.clear();
}
}
SensorClient::~SensorClient()
{
_sensorEventQueue.clear();
ALOGE("shao sensorclient xigou");
}
来看我的调用方式是不是跟Java一样 哈哈哈
#include <jni.h>
#include <string>
#include "LibLoader.h"
#include <iostream>
using namespace std;
typedef void (*__sensor_callback)(void *pCtx, int type, float *dataArray, long timeStamp);
typedef struct {
__sensor_callback cb;
float *dataArray;
void *ctx;
} sensor_call_back_obj;
void MycallBack(void *pCtx, int type, float *dataArray, long timeStamp) {
if (type == 1) {
float value0 = dataArray[0];
float value1 = dataArray[1];
float value2 = dataArray[2];
std::cout << "SACCL" << value0 << "," << value1 << "," << value2 << "," << timeStamp
<< std::endl;
} else if (type == 2) {
float value0 = dataArray[0];
float value1 = dataArray[1];
float value2 = dataArray[2];
std::cout << "SMAG" << value0 << "," << value1 << "," << value2 << "," << timeStamp
<< std::endl;
} else if (type == 4) {
float value0 = dataArray[0];
float value1 = dataArray[1];
float value2 = dataArray[2];
std::cout << "SGYRO" << value0 << "," << value1 << "," << value2 << "," << timeStamp
<< std::endl;
} else if (type == 5) {
float value0 = dataArray[0];
std::cout << "SLIGHT" << value0 << "," << timeStamp << std::endl;
} else if (type == 8) {
float value0 = dataArray[0];
std::cout << "SPROXIMITY" << value0 << timeStamp << std::endl;
}
}
LibLoader *libLoader;
sensor_call_back_obj *listener;
//初始化client返回句柄给下面的接口
extern "C"
JNIEXPORT jlong
JNICALL
Java_nibiruvr_nibiru_test_com_sensornative_MainActivity_initClient(
JNIEnv *env,
jobject /* this */) {
libLoader = new LibLoader();
return libLoader->getSensorFunction();
}
//释放client
extern "C"
JNIEXPORT void
JNICALL
Java_nibiruvr_nibiru_test_com_sensornative_MainActivity_destroyClient(
JNIEnv *env, jobject obj, jlong handler) {
libLoader->mDestroyFunction(handler);
}
//注册监听typedef void (*registerListener)(long nativeReceiver,void* callBackListener,int delay,int count,...);
//count代码后面Sensor type的数量,type用可变参数形式代入
extern "C"
JNIEXPORT void
JNICALL
Java_nibiruvr_nibiru_test_com_sensornative_MainActivity_registerListener(
JNIEnv *env, jobject obj, jlong handler) {
listener = new sensor_call_back_obj();
float *array = new float[20];
listener->ctx = NULL;
listener->dataArray = array;
listener->cb = MycallBack;
libLoader->mRegisterListenerFunction(handler, listener, 10000000, 3, 1, 2, 5, 8);
}
//调用destroyClient()之前请关闭sensor
extern "C"
JNIEXPORT void
JNICALL
Java_nibiruvr_nibiru_test_com_sensornative_MainActivity_disableSensor(
JNIEnv *env, jobject obj, jlong handler) {
libLoader->mDisableFunction(handler, 3, 1, 2, 4);
}