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(near  field  communication)近场通信

传感器的系统结构

传感器系统的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

static JNINativeMethod gMethods[] = {

    {"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

static jint

sensors_module_init(JNIEnv *env, jclass clazz)

{

    SensorManager::getInstance();

    return 0;

}

调用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的几个主要方法:

public class SensorManager{

public Sensor getDefaultSensor(int type) { }  // 取得默认传感器

public List<Sensor> getSensorList(int type) {} //取默认传感器列表

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

public boolean registerListener(SensorListener listener, int sensors) { }//注册传感器的监听者

 public void unregisterListener(SensorListener listener, int sensors) {}//注销注册监听

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

public static final float GRAVITY_***  //重力常量

public static final float MAGNETIC_***磁场常量

public static final float LIGHT_***//亮度传感器

public class Sensor {

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

     public static final int TYPE_ACCELEROMETER = 1;

     public static final int TYPE_MAGNETIC_FIELD = 2;   

     public static final int TYPE_ORIENTATION = 3;

     public static final int TYPE_GYROSCOPE = 4;   

     public static final int TYPE_LIGHT = 5;

     public static final int TYPE_PRESSURE = 6;

     public static final int TYPE_TEMPERATURE = 7;      

     public static final int TYPE_PROXIMITY = 8;     

     public static final int TYPE_GRAVITY = 9;

     public static final int TYPE_LINEAR_ACCELERATION = 10;    

 public static final int TYPE_ROTATION_VECTOR = 11;  

//所有传感器类型

  public static final int TYPE_ALL = -1;

   

    private String  mName;   //名称

    private String  mVendor;  //

private int     mVersion;  //版本

    private int     mType;  //类型

private float   mMaxRange;  //取得传感器的最大范围

 private float   mResolution;// 传感器的解析度

private int     mHandle;   //

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

    private float   mPower;

    private int     mMinDelay;

    private int     mLegacyType;

}


//传感器监听

public interface SensorEventListener {  

    //数值发生变化时调用

    public void onSensorChanged(SensorEvent event);   

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

    public void onAccuracyChanged(Sensor sensor, int accuracy);    

}

 传感器系统的硬件抽象层

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

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

//定义传感器类型

#define SENSOR_TYPE_ACCELEROMETER       1

#define SENSOR_TYPE_MAGNETIC_FIELD      2

#define SENSOR_TYPE_ORIENTATION         3

#define SENSOR_TYPE_GYROSCOPE           4

#define SENSOR_TYPE_LIGHT               5

#define SENSOR_TYPE_PRESSURE            6

#define SENSOR_TYPE_TEMPERATURE         7

#define SENSOR_TYPE_PROXIMITY           8

#define SENSOR_TYPE_GRAVITY             9

#define SENSOR_TYPE_LINEAR_ACCELERATION 10

#define SENSOR_TYPE_ROTATION_VECTOR     11

//hw_module_t common标准的硬件模块

struct sensors_module_t {

    struct hw_module_t common;

//获取传感器列表

     int (*get_sensors_list)(struct sensors_module_t* module,

            struct sensor_t const** list);

};

//传感器的描述性定义

struct sensor_t {

    const char*     name;    

    const char*     vendor;    

    int             version;   

    int             handle;   //传感器的句柄

    int             type;

    float           maxRange;

    float           resolution;

    float           power;    //能耗  ma

    int32_t         minDelay;  

    void*           reserved[8];

};

//表示传感器的数据

 union {

        float           data[16];

         sensors_vec_t   acceleration;  //方向

         sensors_vec_t   magnetic;    //磁矢量

         sensors_vec_t   orientation;  //加速度

         sensors_vec_t   gyro;        //陀螺仪

         float           temperature; //温度

         float           distance;    //距离

         float           light;       //亮度

         float           pressure;   //压强

    };

    uint32_t        reserved1[4];

} sensors_event_t;

//用户控制设备

struct sensors_poll_device_t {

    struct hw_device_t common;   

     int (*activate)(struct sensors_poll_device_t *dev,

            int handle, int enabled);

 

      int (*setDelay)(struct sensors_poll_device_t *dev,

            int handle, int64_t ns);

  

    

    int (*poll)(struct sensors_poll_device_t *dev,

            sensors_event_t* data, int count);

};

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

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

static inline int sensors_open(const struct hw_module_t* module,

        struct sensors_poll_device_t** device) {

    return module->methods->open(module,

            SENSORS_HARDWARE_POLL, (struct hw_device_t**)device);

}

static inline int sensors_close(struct sensors_poll_device_t* device) {

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

}

   硬件抽象层的示例实现

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

//

 static struct hw_module_methods_t sensors_module_methods = {

    .open = open_sensors

};

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

static int

open_sensors(const struct hw_module_t* module,

             const char*               name,

             struct hw_device_t*      *device)

{

    int  status = -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    = (struct hw_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;

    }

    else if (!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  = (struct hw_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;

    }

    return status;

}

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

const struct sensors_module_t HAL_MODULE_INFO_SYM = {

    .common = {

        .tag = HARDWARE_MODULE_TAG,

        .version_major = 1,

        .version_minor = 0,

        .id = SENSORS_HARDWARE_MODULE_ID,

        .name = "Goldfish SENSORS Module",

        .author = "The Android Open Source Project",

        .methods = &sensors_module_methods,

    },

    .get_sensors_list = sensors__get_sensors_list

};

static uint32_t sensors__get_sensors_list(struct sensors_module_t* module,

        struct sensor_t const** list) 

{

    int  fd = qemud_channel_open(SENSORS_SERVICE_NAME);

    char buffer[12];

    int  mask, nn, count;

    int  ret;

    if (fd < 0) {

        E("%s: no qemud connection", __FUNCTION__);

        return 0;

    }

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

    if (ret < 0) {

        E("%s: could not query sensor list: %s", __FUNCTION__,

          strerror(errno));

        close(fd);

        return 0;

    }

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

    if (ret < 0) {

        E("%s: could not receive sensor list: %s", __FUNCTION__,

          strerror(errno));

        close(fd);

        return 0;

    }

    buffer[ret] = 0;

    close(fd);

    /* the result is a integer used as a mask for available sensors */

    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 %d sensors (mask=%d)", __FUNCTION__, count, mask);

    *list = sSensorList;

    return count;

}

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

static const struct sensor_t sSensorListInit[] = {

         //加速度

        { .name       = "Goldfish 3-axis Accelerometer",

          .vendor     = "The Android Open Source Project",

          .version    = 1,

          .handle     = ID_ACCELERATION,

          .type       = SENSOR_TYPE_ACCELEROMETER,

          .maxRange   = 2.8f,

          .resolution = 1.0f/4032.0f,

          .power      = 3.0f,

          .reserved   = {}

        },

        //磁场

        { .name       = "Goldfish 3-axis Magnetic field sensor",

          .vendor     = "The Android Open Source Project",

          .version    = 1,

          .handle     = ID_MAGNETIC_FIELD,

          .type       = SENSOR_TYPE_MAGNETIC_FIELD,

          .maxRange   = 2000.0f,

          .resolution = 1.0f,

          .power      = 6.7f,

          .reserved   = {}

        },

         //方向

        { .name       = "Goldfish Orientation sensor",

          .vendor     = "The Android Open Source Project",

          .version    = 1,

          .handle     = ID_ORIENTATION,

          .type       = SENSOR_TYPE_ORIENTATION,

          .maxRange   = 360.0f,

          .resolution = 1.0f,

          .power      = 9.7f,

          .reserved   = {}

        },

        

        //温度

        { .name       = "Goldfish Temperature sensor",

          .vendor     = "The Android Open Source Project",

          .version    = 1,

          .handle     = ID_TEMPERATURE,

          .type       = SENSOR_TYPE_TEMPERATURE,

          .maxRange   = 80.0f,

          .resolution = 1.0f,

          .power      = 0.0f,

          .reserved   = {}

        },

};

static int

data__poll(struct sensors_data_device_t *dev, sensors_data_t* values)

{

    SensorData*  data = (void*)dev;

    int fd = data->events_fd;

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

    // there are pending sensors, returns them now...

    if (data->pendingSensors) {

        return pick_sensor(data, values);

    }

    // wait until we get a complete event for an enabled sensor

    uint32_t new_sensors = 0;

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

    while (1) {

        /* read the next event */

        char     buff[256];

        int      len = qemud_channel_recv(data->events_fd, buff, sizeof buff-1);

        float    params[3];

        int64_t  event_time;

        if (len < 0) {

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

            return -errno;

        }

        buff[len] = 0;

        /* "wake" is sent from the emulator to exit this loop. This shall

         * really be because another thread called "control__wake" in this

         * process.

         */

        if (!strcmp((const char*)data, "wake")) {

            return 0x7FFFFFFF;

        }

        /* "acceleration:<x>:<y>:<z>" corresponds to an acceleration event */

        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>" is sent when orientation changes */

        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>" is sent for the params of the magnetic field */

        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>" is sent after a series of sensor events.

         * where 'time' is expressed in micro-seconds and corresponds

         * to the VM time when the real poll occured.

         */

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

            if (new_sensors) {

                data->pendingSensors = new_sensors;

                int64_t t = event_time * 1000LL;  /* convert to nano-seconds */

                /* use the time at the first sync: as the base for later

                 * time values */

                if (data->timeStart == 0) {

                    data->timeStart  = data__now_ns();

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

                }

                t += data->timeOffset;

                while (new_sensors) {

                    uint32_t i = 31 - __builtin_clz(new_sensors);

                    new_sensors &= ~(1<<i);

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

                }

                return pick_sensor(data, values);

            } else {

                D("huh ? sync without any sensor data ?");

            }

            continue;

        }

        D("huh ? unsupported command");

    }

}

传感器硬件层实现的要点

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

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

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

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

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

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

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

传感器的使用

 取得SensorManager(系统服务)

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

OrientationEventListener扩展了sensorEventListener

 public OrientationEventListener(Context context, int rate) {

//取得传感器服务

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

        mRate = rate;

        //取得加速度传感器

        mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

        if (mSensor != null) {

            // Create listener only if sensors do exist

            mSensorEventListener = new SensorEventListenerImpl();

        }

}

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

 public void enable() {

        if (mSensor == null) {

            Log.w(TAG"Cannot detect sensors. Not enabled");

            return;

        }

        if (mEnabled == false) {

            if (localLOGV) Log.d(TAG"OrientationEventListener enabled");

            mSensorManager.registerListener(mSensorEventListenermSensormRate);

            mEnabled = true;

        }

    }

    

 class SensorEventListenerImpl implements SensorEventListener {       

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

        public void onSensorChanged(SensorEvent event) {}

}

在清单文件中设置activity属性

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

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

转载于:https://www.cnblogs.com/retacn-yue/archive/2012/09/03/2761387.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Android Studio是Google推出的Android应用程序开发工具,它集成了开发、调试、打包等功能。要学习使用Android Studio,需要了解以下几个方面的知识: 1. Java基础: Android开发是基于Java语言的,所以要学习Android Studio首先要掌握Java基础知识。 2. Android基础: 了解Android操作系统的基本构架和常用组件,如Activity、Service、BroadcastReceiver等。 3. Android Studio使用: 了解Android Studio的基本界面和常用功能,如创建工程、编写代码、调试程序等。 4. Android SDK: 了解Android SDK的安装和配置,以及如何使用SDK Manager来下载SDK并配置项目。 5. 练习实践: 多练习实际项目,熟悉Android Studio的使用,并不断练习和完善自己的技能。 ### 回答2: Android Studio 是一个为 Android 来开发的整体开发环境。它基于 IntelliJ IDEA ,强调速度和智能操作,并致力于为应用程序开发提供高效率的开发工具。Android Studio 的推出,使得 Android 开发者更加容易地创建高质量的应用程序。 首先,要学 Android Studio ,你需要首先了解一些基本知识。学习 Android Studio 的工具包括 Gradle 、 Kotlin 和 Java 等。通过学习这些基础知识,你可以了解不同的语言、工具和框架。 在学习 Android Studio 时要使用实战性的方法。也就是说,每次学习新的东西时,你需要找到一个相关的例子。这样可以帮助你更好地理解它。如果你使用 Android Studio 模板,这将非常有用。这些模板可以帮助你创建常见的应用程序结构,并且你可以基于这些模板创建自己的应用程序。 另外,还有很多不同的工具和插件可以帮助你学习 Android Studio 。例如, Android Studio 网站上有很多有用的文章和教程,可以帮助你更好地理解 Android Studio 。还有很多在线工具可以帮助你实现特定的功能,在初学者阶段,这些工具可以为学习的难度减轻很多。 总之,学习 Android Studio 任重而道远。需要有耐心和时间,还需要不断地尝试和实践。在这个过程中,你可以尝试教学资料、交流学习合作、进一步增强你的知识水平。通过不断的应用和实践,一定可以成为一名优秀的 Android 开发者并圆满地完成应用开发。 ### 回答3: 作为一个应用开发者,学习使用安卓应用程序开发套件非常重要。Android Studio是Google出品的最新安卓开发工具,它具有多种强大的工具和功能,可以极大地提高应用程序的开发效率和质量。在学习过程中,个人对Android Studio的理解主要体现在以下几个方面。 首先,要开始使用Android Studio,需要了解它的基本结构和工具。Android Studio主要由三个主要组件组成:IDE、SDK、和Emulator。IDE是开发者使用的主要工具。它提供了编写、测试和调试代码所需的所有基本功能,包括视觉化设计器,代码编辑器和调试工具。SDK是开发应用程序所需的软件开发包。它包括实用程序和库,可用于在应用程序中实现预定功能。Emulator是一个虚拟的安卓设备,可以用来在开发应用程序时模拟真实设备上的应用程序运行情况。 其次,一些基本的编程知识也必不可少,例如Java编程、XML语言、UI界面设计等。JavaAndroid Studio中最常用的编程语言,用于编写应用程序的逻辑代码;XML语言则用于设计UI界面。在学习这些基本知识时,建议首先了解Java语言特性和面向对象编程理念,熟悉它们的基本语法和数据类型。同时,也可以通过在线教程和网课等方式加强对UI设计和布局的理解。 最后,学会使用网上的资源和社区的帮助非常重要。Android Studio的开发者社区很大,有很多在线资源可以帮助开发者的开发学习,例如stack overflow、CSDN社区等。同时,Google官方的开发者网站也提供了大量的文档资料、教程、API使用说明等。 总之,Android Studio的学习需要进行持续不断的针对不同方面的学习和实践。要充分运用Android Studio的强大功能,建议在掌握基础知识的基础上,多做实际的项目练习,不断提高自己的技术水平和代码能力,才能成为一名优秀的安卓应用程序开发者。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值