Android C++ 实现SensorEventListener

     做Android开发的童鞋都玩过SensorEventListener去监听Sensor设备的数据包括加速度,陀螺仪,地磁,光感,距感

     现在我们要玩的是用C++去封装动态库实现SensorEventListener

     通过这篇文章你会深刻明白EventListner的本质是什么?

     我先概括SensorEventListener本质是什么:Framework Nativie层有个SensorService去poll Sensor设备数据。app每次调用registerListener其实就是建立个Bittube管道实现进程通信,每次有数据来的时候就通过JNI调用onSensorChanged()回调通知APP

    

   我这边只给出实现代码,具体的逻辑需要读者去参考我的博文http://blog.csdn.net/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);
}



  

    

    

  

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值