• android重力感应开发

    2015-08-02 23:03:28
    Android2.3 gingerbread系统中,google提供了11种传感器供应用层使用,具体如下:(Sensor类) #define SENSOR_TYPE_ACCELEROMETER 1 //加速度 #define SENSOR_TYPE_MAGNETIC_FIELD 2 //磁力 #define SENSOR_...

    一、手机中常用的传感器

    在Android2.3 gingerbread系统中,google提供了11种传感器供应用层使用,具体如下:(Sensor类)

    #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//旋转矢量


    1-1加速度传感器

    加速度传感器又叫G-sensor,返回x、y、z三轴的加速度数值。
    该数值包含地心引力的影响,单位是m/s^2。
    将手机平放在桌面上,x轴默认为0,y轴默认0,z轴默认9.81。
    将手机朝下放在桌面上,z轴为-9.81。
    将手机向左倾斜,x轴为正值。
    将手机向右倾斜,x轴为负值。
    将手机向上倾斜,y轴为负值。
    将手机向下倾斜,y轴为正值。
    加速度传感器可能是最为成熟的一种mems产品,市场上的加速度传感器种类很多。
    手机中常用的加速度传感器有BOSCH(博世)的BMA系列,AMK的897X系列,ST的LIS3X系列等。
    这些传感器一般提供±2G至±16G的加速度测量范围,采用I2C或SPI接口和MCU相连,数据精度小于16bit。


    Android开发之重力传感器





    1-2 磁力传感器

    磁力传感器简称为M-sensor,返回x、y、z三轴的环境磁场数据。
    该数值的单位是微特斯拉(micro-Tesla),用uT表示。
    单位也可以是高斯(Gauss),1Tesla=10000Gauss。
    硬件上一般没有独立的磁力传感器,磁力数据由电子罗盘传感器提供(E-compass)。
    电子罗盘传感器同时提供下文的方向传感器数据。

    1-3 方向传感器

    方向传感器简称为O-sensor,返回三轴的角度数据,方向数据的单位是角度。
    为了得到精确的角度数据,E-compass需要获取G-sensor的数据,
    经过计算生产O-sensor数据,否则只能获取水平方向的角度。
    方向传感器提供三个数据,分别为azimuth、pitch和roll。
    azimuth:方位,返回水平时磁北极和Y轴的夹角,范围为0°至360°。
    0°=北,90°=东,180°=南,270°=西。
    pitch:x轴和水平面的夹角,范围为-180°至180°。
    当z轴向y轴转动时,角度为正值。
    roll:y轴和水平面的夹角,由于历史原因,范围为-90°至90°。
    当x轴向z轴移动时,角度为正值。
    电子罗盘在获取正确的数据前需要进行校准,通常可用8字校准法。
    8字校准法要求用户使用需要校准的设备在空中做8字晃动,
    原则上尽量多的让设备法线方向指向空间的所有8个象限。
    手机中使用的电子罗盘芯片有AKM公司的897X系列,ST公司的LSM系列以及雅马哈公司等等。
    由于需要读取G-sensor数据并计算出M-sensor和O-sensor数据,
    因此厂商一般会提供一个后台daemon来完成工作,电子罗盘算法一般是公司私有产权。

    1-4 陀螺仪传感器

    陀螺仪传感器叫做Gyro-sensor,返回x、y、z三轴的角加速度数据。
    角加速度的单位是radians/second。
    根据Nexus S手机实测:
    水平逆时针旋转,Z轴为正。
    水平逆时针旋转,z轴为负。
    向左旋转,y轴为负。
    向右旋转,y轴为正。
    向上旋转,x轴为负。
    向下旋转,x轴为正。
    ST的L3G系列的陀螺仪传感器比较流行,iphone4和google的nexus s中使用该种传感器。

    1-5 光线感应传感器

    光线感应传感器检测实时的光线强度,光强单位是lux,其物理意义是照射到单位面积上的光通量。
    光线感应传感器主要用于Android系统的LCD自动亮度功能。
    可以根据采样到的光强数值实时调整LCD的亮度。

    1-6 压力传感器

    压力传感器返回当前的压强,单位是百帕斯卡hectopascal(hPa)。

    1-7 温度传感器

    温度传感器返回当前的温度。

    1-8 接近传感器

    接近传感器检测物体与手机的距离,单位是厘米。
    一些接近传感器只能返回远和近两个状态,
    因此,接近传感器将最大距离返回远状态,小于最大距离返回近状态。
    接近传感器可用于接听电话时自动关闭LCD屏幕以节省电量。
    一些芯片集成了接近传感器和光线传感器两者功能。
    下面三个传感器是Android2新提出的传感器类型,目前还不太清楚有哪些应用程序使用。

    1-9 重力传感器

    重力传感器简称GV-sensor,输出重力数据。
    在地球上,重力数值为9.8,单位是m/s^2。
    坐标系统与加速度传感器相同。
    当设备复位时,重力传感器的输出与加速度传感器相同。

    1-10 线性加速度传感器

    线性加速度传感器简称LA-sensor。
    线性加速度传感器是加速度传感器减去重力影响获取的数据。
    单位是m/s^2,坐标系统与加速度传感器相同。
    加速度传感器、重力传感器和线性加速度传感器的计算公式如下:
    加速度 = 重力 + 线性加速度

    1-11 旋转矢量传感器

    旋转矢量传感器简称RV-sensor。
    旋转矢量代表设备的方向,是一个将坐标轴和角度混合计算得到的数据。
    RV-sensor输出三个数据:
    x*sin(theta/2)
    y*sin(theta/2)
    z*sin(theta/2)
    sin(theta/2)是RV的数量级。
    RV的方向与轴旋转的方向相同。
    RV的三个数值,与cos(theta/2)组成一个四元组。
    RV的数据没有单位,使用的坐标系与加速度相同。
    举例:
    sensors_event_t.data[0] = x*sin(theta/2)
    sensors_event_t.data[1] = y*sin(theta/2)
    sensors_event_t.data[2] = z*sin(theta/2)
    sensors_event_t.data[3] = cos(theta/2)
    GV、LA和RV的数值没有物理传感器可以直接给出,
    需要G-sensor、O-sensor和Gyro-sensor经过算法计算后得出。
    算法一般是传感器公司的私有产权。





    二、Android感应检测管理---SensorManager

    1、取得SensorManager


    使用感应检测Sensor首要先获取感应设备的检测信号,你可以调用Context.getSysteService(SENSER_SERVICE)方法来取得感应检测的服务

    2、实现取得感应检测Sensor状态的监听功能


    实现以下两个SensorEventListener方法来监听,并取得感应检测Sensor状态:

    //在感应检测到Sensor的精密度有变化时被调用到。   
    public void onAccuracyChanged(Senso sensor,int accuracy);  
    //在感应检测到Sensor的值有变化时会被调用到。   
    public void onSensorChanged(SensorEvent event);  




    3、实现取得感应检测Sensor目标各类的值

    实现下列getSensorList()方法来取得感应检测Sensor的值;
            List<Sensor> sensors = sm.getSensorList(Sensor.TYPE_TEMPERATURE);  


    4、注册SensorListener

    sm.regesterListener(SensorEventListener listener, Sensor sensor, int rate);  

            第一个参数:监听Sensor事件,第二个参数是Sensor目标种类的值,第三个参数是延迟时间的精度密度。延迟时间的精密度参数如下:

    参数

    延迟时间

    SensorManager.SENSOR_DELAY_FASTEST

    0ms

    SensorManager.SENSOR_DELAY_GAME

    20ms

    SensorManager.SENSOR_DELAY_UI

    60ms

    SensorManager.SENSOR_DELAY_NORMAL

    200ms



    因为感应检测Sensor的服务是否频繁和快慢都与电池参量的消耗有关,同时也会影响处理的效率,所以兼顾到消耗电池和处理效率的平衡,设置感应检测Sensor的延迟时间是一门重要的学问,需要根据应用系统的需求来做适当的设置。
    感应检测Sensor的硬件检测组件受不同的厂商提供。你可以采用Sensor的getVendor(),Sensor()的getName()和Sensor的getVeesrion()方法来取得 厂商的名称、产品和版本。

    5、取消注册

    sm.unregisterListener(SensorEventListener listener)  


    6、感应检测

    加速度感应检测——Accelerometer

    Accelerometer Sensor测量的是所有施加在设备上的力所产生的加速度的负值(包括重力加速度)。加速度所使用的单位是m/sec^2,数值是加速度的负值。

    SensorEvent.values[0]:加速度在X轴的负值
    SensorEvent.values[1]:加速度在Y轴的负值
    SensorEvent.values[2]:加速度在Z轴的负值

    例如:

    当手机Z轴朝上平放在桌面上,并且从左到右推动手机,此时X轴上的加速度是正数。

    当手机Z轴朝上静止放在桌面上,此时Z轴的加速度是+9.81m/sec^2。

    当手机从空中自由落体,此时加速度是0

    当手机向上以Am/sec^2的加速度向空中抛出,此时加速度是A+9.81m/sec^2

    重力加速度感应检测——Gravity

    重力加速度,其单位是m/sec^2,其坐标系与Accelerometer使用的一致。当手机静止时,gravity的值和Accelerometer的值是一致的。

    线性加速度感应检测——Linear-Acceleration

    Accelerometer、Gravity和Linear-Acceleration三者的关系如下公式:

    accelerometer = gravity + linear-acceleration

    地磁场感应检测——Magnetic-field

    地磁场的单位是micro-Tesla(uT),检测的是X、Y、Z轴上的绝对地磁场。

    陀螺仪感应检测——Gyroscope

    陀螺仪的单位是弧度/秒,测量的是物体分别围绕X,Y,Z轴旋转的角速度。它的坐标系与加速度传感器的坐标系相同。逆时针方向旋转的角度正的。也就是说,如果设备逆时针旋转,观察者向X,Y,Z轴的正方向看去,就报告设备是正转的。请注意,这是标准的正旋转的数学定义。

    光线感应检测——Light

    values[0]:表示环境光照的水平,单位是SI lux。

    位置逼近感应检测——Proximity

    values[0]:逼近的距离,单位是厘米(cm)。有一些传感器只能支持近和远两种状态,这种情况下,传感器必须报告它在远状态下的maximum_range值和在近状态下的小值。

    旋转矢量感应检测——Rotation Vector

    旋转向量是用来表示设备的方向,它是由角度和轴组成,就是设备围绕x,y,z轴之一旋转θ角度。旋转向量的三个要素是,这样旋转向量的大小等于sin(θ/2),旋转向量的方向等于旋转轴的方向。

    values[0]: x*sin(θ/2) 
    values[1]: y*sin(θ/2) 
    values[2]: z*sin(θ/2) 
    values[3]: cos(θ/2) (optional: only if value.length = 4)

    方向感应检测——Orientation

    其单位是角度

    values[0]: Azimuth(方位),地磁北方向与y轴的角度,围绕z轴旋转(0到359)。0=North, 90=East, 180=South, 270=West 
    values[1]: Pitch(俯仰),围绕X轴旋转(-180 to 180), 当Z轴向Y轴运动时是正值
    values[2]: Roll(滚),围绕Y轴旋转(-90 to 90),当X轴向Z轴运动时是正值 


    实例:

    /*
    *当手机正面朝上的时候,z的值为q,反面朝上的时候,z的值为-g
    当手机右侧面朝上的时候,x的值为g,右侧面朝上的时候,x的值为-g
    当手机上侧面朝上的时候,y的值为g,右侧面朝上的时候,y的值为-g
    *
    */
    
    public class MainActivity extends ActionBarActivity {
        /**
         * 创建一个传感器管理器和一个传感器监听器,管理器用来管理传感器以及创建各种各样的传感器,
         * 监听器用来监视传感器的变化并且进行相应的操作
         **/
        private SensorManager mSensorManager;
        private Sensor mSensor;
    
        TextView textView;
    
        float x,y;
    
        private static final String TAG = MainActivity.class.getSimpleName();
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            textView = (TextView) findViewById(R.id.textView);
    
            //获得重力感应硬件控制器
            mSensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
            mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    
            if (null == mSensorManager) {
                Log.d(TAG, "deveice not support SensorManager");
            }
    
            //添加重力感应监听,并实现其方法
            SensorEventListener sensorEventListener = new SensorEventListener() {
                @Override
                public void onSensorChanged(SensorEvent event) {
    
                    if (event.sensor == null) {
                        return;
                    }
    
                    if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
                    x = event.values[SensorManager.DATA_X];
                    y = event.values[SensorManager.DATA_Y];
    <span style="white-space:pre">		</span>//z = .....
                    textView.setText("x="+(int)x+"y="+(int)y);
                    }
                }
    
                @Override
                public void onAccuracyChanged(Sensor sensor, int accuracy) {
    
                }
            };
    
            //注册Listener,SENSOR_DELAY_GAME为检测的精确度,
            mSensorManager.registerListener(sensorEventListener, mSensor,SensorManager.SENSOR_DELAY_GAME);
    
        }
    }
    

    转载自:http://blog.csdn.net/mad1989/article/details/20848181


    展开全文
  • 在实际开发中我遇到一个让人很蛋疼的问题,大致是当我点击某一个按钮的时候,强制切换为横屏显示,这个很容易做到,只需在onclick里面调用...可是这回我已经去掉了屏幕随重力感应变化而变化的响应

    在实际开发中我遇到一个让人很蛋疼的问题,大致是当我点击某一个按钮的时候,强制切换为横屏显示,这个很容易做到,只需在onclick里面调用setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE),就能做到了。但是需求说还没完,当我横屏看完了之后,我把手机竖起来,又能切换成竖屏。可是这回我已经去掉了屏幕随重力感应变化而变化的响应了,除非再次调用setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR),注意参数。

    貌似在activity中没有像oncreate这种生命周期回调函数一样来处理重力感应变化的重写方法。网上找了很久,才发现有一个叫做传感器的东西。这里要强调的是,虽然横竖屏切换与重力感应貌似有关,其实他们是两回事。横竖屏在重力感应中只是最粗略的说法了,你把手机平放着不动,重力感应都是时时刻刻发生着的,因为安卓设备能感应到很细微的震动。

    Android中检测重力感应变化大致需要下面几个步骤:

    1) 得到传感器服务 getSystemService(SENSOR_SERVICE);

    得到一个SensorManager,用来管理分配调度处理Sensor的工作,注意它并不服务运行于后台,真正属于Sensor的系统服务是SensorService,终端下#service list可以看到sensorservice: [android.gui.SensorServer]

    2) 得到传感器类型 getDefaultSensor(Sensor.TYPE_GRAVITY);

    当然还有各种千奇百怪的传感器,可以查阅Android官网API或者源码Sensor.java。

    3) 注册监听器 SensorEventListener

    应用程序打开一个监听接口,专门处理传感器的数据,这个监听机制比较重要,被系统广泛使用。

    4) 实现监听器的回调函数 onSensorChanged, onAccuracyChanged

    很多移动设备都内置了感应器,android通过Sensor和SensorManager类抽象了这些感应器,通过这些类可以使用android设备的传感器

    =================================================================

    一 、介绍Sensor类

    SDK只有一句介绍“Class representing a sensor. Use getSensorList(int) to get the list of available Sensors.”,表示一个感应器的类,可以使用getSensorList方法(此方法属于接下来要讲的SensorManager)获得所有可用的感应器,该方法返回的是一个List

    下面的列表显示了,Sensor所提供的所有服务

    Constants
    int TYPE_ACCELEROMETER A constant describing an accelerometer sensor type. //三轴加速度感应器 返回三个坐标轴的加速度 单位m/s2
    int TYPE_ALL A constant describing all sensor types. //用于列出所有感应器
    int TYPE_GRAVITY A constant describing a gravity sensor type. //重力感应器
    int TYPE_GYROSCOPE A constant describing a gyroscope sensor type //陀螺仪 可判断方向 返回三个坐标轴上的角度
    int TYPE_LIGHT A constant describing an light sensor type. //光线感应器 单位 lux 勒克斯
    int TYPE_LINEAR_ACCELERATION A constant describing a linear acceleration sensor type. //线性加速度
    int TYPE_MAGNETIC_FIELD A constant describing a magnetic field sensor type. //磁场感应 返回三个坐标轴的数值 微特斯拉
    int TYPE_ORIENTATION This constant is deprecated. use SensorManager.getOrientation() instead. //方向感应器 已过时 可以使用方法获得
    int TYPE_PRESSURE A constant describing a pressure sensor type //压力感应器 单位 千帕斯卡
    int TYPE_PROXIMITY A constant describing an proximity sensor type. //距离传感器
    int TYPE_ROTATION_VECTOR A constant describing a rotation vector sensor type. //翻转传感器
    int TYPE_TEMPERATURE A constant describing a temperature sensor type //温度传感器 单位 摄氏度

    此类中包含的方法都是get型的 用来获取所选sensor的一些属性,sensor类一般不需要new而是通过SensorManager的方法获得

    二 介绍SensorManager类

    SDK解释:“SensorManager lets you access the device’s sensors. Get an instance of this class by calling Context.getSystemService() with the argument SENSOR_SERVICE.
    Always make sure to disable sensors you don’t need, especially when your activity is paused. Failing to do so can drain the battery in just a few hours. Note that the system will not disable sensors automatically when the screen turns off. ”
    SensorManager 允许你访问设备的感应器。通过传入参数SENSOR_SERVICE参数调用Context.getSystemService方法可以获得一个sensor的实例。永远记得确保当你不需要的时候,特别是Activity暂定的时候,要关闭感应器。忽略这一点肯能导致几个小时就耗尽电池,注意当屏幕关闭时,系统不会自动关闭感应器。

    三 常用的感应器

    (1)获取加速度: 加速度感应器

    可以通过这个感应器获得三个浮点型

    x-axis
    y-axis

    z-axis

    可参阅《android 高级编程2》中的一个插图分析次数据
    这里写图片描述
    X Y Z分别对应values[0]到[2]

    X表示左右移动的加速度

    Y表示前后移动的加速度

    Z表示垂直方向的加速度 (测试时发现,将手机置于水平桌面稳定后 XY均为0 Z的值为9.4 约等于重力加速度,依次可以做一个简单的算法实现重力测力计,有时间会给大家一个例子)

    =================================================================

    下面先看一个基本的获取加速的demo,希望大家好好注意代码中的注释

    /* 
     * @author octobershiner 
     * 2011 07 27 
     * SE.HIT 
     * 一个演示android加速度感应器的例子 
     * */
    
    package uni.sensor; 
    
    import java.util.Iterator; 
    import java.util.List; 
    
    import android.app.Activity; 
    import android.content.Context; 
    import android.hardware.Sensor; 
    import android.hardware.SensorEvent; 
    import android.hardware.SensorEventListener; 
    import android.hardware.SensorManager; 
    import android.os.Bundle; 
    import android.util.Log; 
    
    public class SensorDemoActivity extends Activity { 
        /** Called when the activity is first created. */
        //设置LOG标签 
        private static final String TAG = "sensor"; 
        private  SensorManager sm; 
        @Override 
        public void onCreate(Bundle savedInstanceState) { 
            super.onCreate(savedInstanceState); 
            setContentView(R.layout.main); 
            //创建一个SensorManager来获取系统的传感器服务 
            sm = (SensorManager)getSystemService(Context.SENSOR_SERVICE); 
            //选取加速度感应器 
            int sensorType = Sensor.TYPE_ACCELEROMETER; 
    
            /* 
             * 最常用的一个方法 注册事件 
             * 参数1 :SensorEventListener监听器 
             * 参数2 :Sensor 一个服务可能有多个Sensor实现,此处调用getDefaultSensor获取默认的Sensor 
             * 参数3 :模式 可选数据变化的刷新频率 
             * */
            sm.registerListener(myAccelerometerListener,sm.getDefaultSensor(sensorType),SensorManager.SENSOR_DELAY_NORMAL); 
    
        } 
    
        /* 
         * SensorEventListener接口的实现,需要实现两个方法 
         * 方法1 onSensorChanged 当数据变化的时候被触发调用 
         * 方法2 onAccuracyChanged 当获得数据的精度发生变化的时候被调用,比如突然无法获得数据时 
         * */
        final SensorEventListener myAccelerometerListener = new SensorEventListener(){ 
    
            //复写onSensorChanged方法 
            public void onSensorChanged(SensorEvent sensorEvent){ 
                if(sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER){ 
                    Log.i(TAG,"onSensorChanged"); 
    
                    //图解中已经解释三个值的含义 
                    float X_lateral = sensorEvent.values[0]; 
                    float Y_longitudinal = sensorEvent.values[1]; 
                    float Z_vertical = sensorEvent.values[2]; 
                    Log.i(TAG,"\n heading "+X_lateral); 
                    Log.i(TAG,"\n pitch "+Y_longitudinal); 
                    Log.i(TAG,"\n roll "+Z_vertical); 
                } 
            } 
            //复写onAccuracyChanged方法 
            public void onAccuracyChanged(Sensor sensor , int accuracy){ 
                Log.i(TAG, "onAccuracyChanged"); 
            } 
        }; 
    
        public void onPause(){ 
            /* 
             * 很关键的部分:注意,说明文档中提到,即使activity不可见的时候,感应器依然会继续的工作,测试的时候可以发现,没有正常的刷新频率 
             * 也会非常高,所以一定要在onPause方法中关闭触发器,否则讲耗费用户大量电量,很不负责。 
             * */
            sm.unregisterListener(myAccelerometerListener); 
            super.onPause(); 
        } 
    
    }

    测试的时候会发现刷新的特别快,这就引出一个问题,如果真的要呈现在UI中的话,就会不断的绘制界面,非常耗费资源,所以《android高级编程》中给出了一个方案就是引入新的线程来刷新界面。

    2)获取用户移动方向

    其实获取方向本应该很简单的事情,在文章前面部分看到 有个TYPE_ORIENTATION 关键字,说明可以直接获取设备的移动方向,但是最新版的SDK加上了这么一句话“TYPE_ORIENTATION This constant is deprecated. use SensorManager.getOrientation() instead. ”也就是说,这种方式已经被取消,要开发者使用 SensorManager.getOrientation()来获取原来的数据。

    实际上,android获取方向是通过磁场感应器和加速度感应器共同获得的,至于具体的算法SDK已经封装好了。也就是说现在获取用户方向有两种方式,一是官方推荐的,通过SensorManager.getOrientation()来获取,这个方法表面看似容易(那是因为你还没看到他的参数。。一会再说),但实际上需要用到两个感应器共同完成工作,特点是更加的准确。第二种方法非常简单,就像前一篇文章获取加速度一样,直接得到三个轴上的数据。从难一些的介绍吧,因为毕竟第一种方法会是android未来的一个选择,第二种不知道什么时候就要成为历史了。

    android给我们提供的方向数据是一个float型的数组,包含三个方向的值如图
    这里写图片描述
    当你的手机水平放置时,被默认为静置状态,即XY角度均为0

    values[0] 表示Z轴的角度:方向角,我们平时判断的东西南北就是看这个数据的,经过我的实验,发现了一个有意思的事情,也就是说使用第一种方式获得方向(磁场+加速度)得到的数据范围是(-180~180),也就是说,0表示正北,90表示正东,180/-180表示正南,-90表示正西。而第二种方式(直接通过方向感应器)数据范围是(0~360)360/0表示正北,90表示正东,180表示正南,270表示正西。

    values[1] 表示X轴的角度:俯仰角 即由静止状态开始,前后翻转

    values[2] 表示Y轴的角度:翻转角 即由静止状态开始,左右翻转

    可见统一获取方向的方法是必须的,因为处理这些数据的算法可能针对第一种获取方式,那么当用在第二种方式时,移植性就不好了。

    看下面的方法

    public static float[] getOrientation(float[] R, float[] values)
    Since: API Level 3
    Computes the device’s orientation based on the rotation matrix.

    When it returns, the array values is filled with the result:

    values[0]: azimuth, rotation around the Z axis.
    values[1]: pitch, rotation around the X axis.
    values[2]: roll, rotation around the Y axis.
    The reference coordinate-system used is different from the world coordinate-system defined for the rotation matrix:

    X is defined as the vector product Y.Z(It is tangential to the ground at the device’s current location and roughly points West).
    Y is tangential to the ground at the device’s current location and points towards the magnetic North Pole.
    Z points towards the center of the Earth and is perpendicular to the ground.
    All three angles above are in radiansand positivein the counter-clockwisedirection.

    通常我们并不需要获取这个函数的返回值,这个方法会根据参数R[]的数据填充values[]而后者就是我们想要的。

    那么R表示什么呢?又将怎么获取呢?

    R[] 是一个旋转矩阵,用来保存磁场和加速度的数据,大家可以理解未加工的方向数据吧

    R通过下面的静态方法获取,这个方法也是用来填充R[]

    public static boolean getRotationMatrix(float[] R, float[] I, float[] gravity, float[] geomagnetic)

    解释以下参数,第一个就是我们需要填充的R数组,大小是9
    第二个是是一个转换矩阵,将磁场数据转换进实际的重力坐标中 一般默认情况下可以设置为null

    第三个是一个大小为3的数组,表示从加速度感应器获取来的数据 在onSensorChanged中

    第四个是一个大小为3的数组,表示从磁场感应器获取来的数据 在onSensorChanged中

    ==============================================================

    好了基本逻辑就是这样的,下面给大家演示一个简单的测试方向的例子,可以时刻监听用户的方向

    /* 
     * @author octobershiner 
     * 2011 07 28 
     * SE.HIT 
     * 一个演示通过磁场和加速度两个感应器获取方向数据的例子 
     * */
    
    
    package uni.sensor; 
    
    import android.app.Activity; 
    import android.content.Context; 
    import android.hardware.Sensor; 
    import android.hardware.SensorEvent; 
    import android.hardware.SensorEventListener; 
    import android.hardware.SensorManager; 
    import android.os.Bundle; 
    import android.util.Log; 
    
    public class OrientationActivity extends Activity{ 
    
        private SensorManager sm; 
        //需要两个Sensor 
        private Sensor aSensor; 
        private Sensor mSensor; 
    
        float[] accelerometerValues = new float[3]; 
        float[] magneticFieldValues = new float[3]; 
    
        private static final String TAG = "sensor"; 
    
        @Override 
        public void onCreate(Bundle savedInstanceState) { 
            // TODO Auto-generated method stub 
            super.onCreate(savedInstanceState); 
            setContentView(R.layout.main); 
    
            sm = (SensorManager)getSystemService(Context.SENSOR_SERVICE); 
            aSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 
            mSensor = sm.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); 
    
            sm.registerListener(myListener, aSensor, SensorManager.SENSOR_DELAY_NORMAL); 
            sm.registerListener(myListener, mSensor,SensorManager.SENSOR_DELAY_NORMAL); 
            //更新显示数据的方法 
            calculateOrientation(); 
    
        } 
        //再次强调:注意activity暂停的时候释放 
        public void onPause(){ 
            sm.unregisterListener(myListener); 
            super.onPause(); 
        }    
    
    
        final SensorEventListener myListener = new SensorEventListener() { 
        public void onSensorChanged(SensorEvent sensorEvent) { 
    
        if (sensorEvent.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) 
        magneticFieldValues = sensorEvent.values; 
        if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) 
            accelerometerValues = sensorEvent.values; 
        calculateOrientation(); 
        } 
        public void onAccuracyChanged(Sensor sensor, int accuracy) {} 
        }; 
    
    
        private  void calculateOrientation() { 
              float[] values = new float[3]; 
              float[] R = new float[9]; 
              SensorManager.getRotationMatrix(R, null, accelerometerValues, magneticFieldValues);          
              SensorManager.getOrientation(R, values); 
    
              // 要经过一次数据格式的转换,转换为度 
              values[0] = (float) Math.toDegrees(values[0]); 
              Log.i(TAG, values[0]+""); 
              //values[1] = (float) Math.toDegrees(values[1]); 
              //values[2] = (float) Math.toDegrees(values[2]); 
    
              if(values[0] >= -5 && values[0] < 5){ 
                 Log.i(TAG, "正北"); 
              } 
              else if(values[0] >= 5 && values[0] < 85){ 
                  Log.i(TAG, "东北"); 
              } 
              else if(values[0] >= 85 && values[0] <=95){ 
                  Log.i(TAG, "正东"); 
              } 
              else if(values[0] >= 95 && values[0] <175){ 
                  Log.i(TAG, "东南"); 
              } 
              else if((values[0] >= 175 && values[0] <= 180) || (values[0]) >= -180 && values[0] < -175){ 
                  Log.i(TAG, "正南"); 
              } 
              else if(values[0] >= -175 && values[0] <-95){ 
                  Log.i(TAG, "西南"); 
              } 
              else if(values[0] >= -95 && values[0] < -85){ 
                  Log.i(TAG, "正西"); 
              } 
              else if(values[0] >= -85 && values[0] <-5){ 
                  Log.i(TAG, "西北"); 
              } 
            } 
    
    
    }

    第二种方法,和这种比起来简单很多,其实大家可以完全参考获取加速度例子中的代码

    只要把其中的两个Sensor.TYPE_ACCELEROMETER改成 Sensor.TYPE_ORIENTATIO就好了,但是第一种方法大家最好掌握,这应该是未来android的标准

    展开全文
  • android 感应

    2016-11-16 15:30:43
    Android中检测重力感应变化大致需要下面几个步骤:1) 得到传感器服务 getSystemService(SENSOR_SERVICE);得到一个SensorManager,用来管理分配调度处理Sensor的工作,注意它并不服务运行于后台,真正属于Sensor的...

    Android中检测重力感应变化大致需要下面几个步骤:

    1) 得到传感器服务 getSystemService(SENSOR_SERVICE);

    得到一个SensorManager,用来管理分配调度处理Sensor的工作,注意它并不服务运行于后台,真正属于Sensor的系统服务是SensorService,终端下#service list可以看到sensorservice: [android.gui.SensorServer]。

    2) 得到传感器类型 getDefaultSensor(Sensor.TYPE_GRAVITY);

    当然还有各种千奇百怪的传感器,可以查阅Android官网API或者源码Sensor.java。

    3) 注册监听器 SensorEventListener

    应用程序打开一个监听接口,专门处理传感器的数据,这个监听机制比较重要,被系统广泛使用。

    4) 实现监听器的回调函数 onSensorChanged, onAccuracyChanged

    很多移动设备都内置了感应器,android通过Sensor和SensorManager类抽象了这些感应器,通过这些类可以使用android设备的传感器

    一 介绍Sensor类

    SDK只有一句介绍“Class representing a sensor. Use getSensorList(int) to get the list of available Sensors.”,表示一个感应器的类,可以使用getSensorList方法(此方法属于接下来要讲的SensorManager)获得所有可用的感应器,该方法返回的是一个List

    下面的列表显示了,Sensor所提供的所有服务

    Constants
    int TYPE_ACCELEROMETER A constant describing an accelerometer sensor type. //三轴加速度感应器 返回三个坐标轴的加速度 单位m/s2
    int TYPE_ALL A constant describing all sensor types. //用于列出所有感应器
    int TYPE_GRAVITY A constant describing a gravity sensor type. //重力感应器
    int TYPE_GYROSCOPE A constant describing a gyroscope sensor type //陀螺仪 可判断方向 返回三个坐标轴上的角度
    int TYPE_LIGHT A constant describing an light sensor type. //光线感应器 单位 lux 勒克斯
    int TYPE_LINEAR_ACCELERATION A constant describing a linear acceleration sensor type. //线性加速度
    int TYPE_MAGNETIC_FIELD A constant describing a magnetic field sensor type. //磁场感应 返回三个坐标轴的数值 微特斯拉
    int TYPE_ORIENTATION This constant is deprecated. use SensorManager.getOrientation() instead. //方向感应器 已过时 可以使用方法获得
    int TYPE_PRESSURE A constant describing a pressure sensor type //压力感应器 单位 千帕斯卡
    int TYPE_PROXIMITY A constant describing an proximity sensor type. //距离传感器
    int TYPE_ROTATION_VECTOR A constant describing a rotation vector sensor type. //翻转传感器
    int TYPE_TEMPERATURE A constant describing a temperature sensor type //温度传感器 单位 摄氏度


    此类中包含的方法都是get型的 用来获取所选sensor的一些属性,sensor类一般不需要new而是通过SensorManager的方法获得

    二 介绍SensorManager类

    SDK解释:“SensorManager lets you access the device’s sensors. Get an instance of this class by calling Context.getSystemService() with the argument SENSOR_SERVICE.
    Always make sure to disable sensors you don’t need, especially when your activity is paused. Failing to do so can drain the battery in just a few hours. Note that the system will not disable sensors automatically when the screen turns off. ”
    SensorManager 允许你访问设备的感应器。通过传入参数SENSOR_SERVICE参数调用Context.getSystemService方法可以获得一个sensor的实例。永远记得确保当你不需要的时候,特别是Activity暂定的时候,要关闭感应器。忽略这一点肯能导致几个小时就耗尽电池,注意当屏幕关闭时,系统不会自动关闭感应器。

    三 常用的感应器

    (1)获取加速度: 加速度感应器

    可以通过这个感应器获得三个浮点型

    x-axis
    y-axis

    z-axis

    可参阅《android 高级编程2》中的一个插图分析次数据

    X Y Z分别对应values[0]到[2]

    X表示左右移动的加速度

    Y表示前后移动的加速度

    Z表示垂直方向的加速度 (测试时发现,将手机置于水平桌面稳定后 XY均为0 Z的值为9.4 约等于重力加速度,依次可以做一个简单的算法实现重力测力计,有时间会给大家一个例子)

    下面先看一个基本的获取加速的demo,希望大家好好注意代码中的注释

    1./*
    2. * @author octobershiner
    3. * 2011 07 27
    4. * SE.HIT
    5. * 一个演示android加速度感应器的例子
    6. * */
    7.
    8.package uni.sensor;
    9.
    10.import java.util.Iterator;
    11.import java.util.List;
    12.
    13.import android.app.Activity;
    14.import android.content.Context;
    15.import android.hardware.Sensor;
    16.import android.hardware.SensorEvent;
    17.import android.hardware.SensorEventListener;
    18.import android.hardware.SensorManager;
    19.import android.os.Bundle;
    20.import android.util.Log;
    21.
    22.public class SensorDemoActivity extends Activity {
    23. /* Called when the activity is first created. /
    24. //设置LOG标签
    25. private static final String TAG = “sensor”;
    26. private SensorManager sm;
    27. @Override
    28. public void onCreate(Bundle savedInstanceState) {
    29. super.onCreate(savedInstanceState);
    30. setContentView(R.layout.main);
    31. //创建一个SensorManager来获取系统的传感器服务
    32. sm = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
    33. //选取加速度感应器
    34. int sensorType = Sensor.TYPE_ACCELEROMETER;
    35.
    36. /*
    37. * 最常用的一个方法 注册事件
    38. * 参数1 :SensorEventListener监听器
    39. * 参数2 :Sensor 一个服务可能有多个Sensor实现,此处调用getDefaultSensor获取默认的Sensor
    40. * 参数3 :模式 可选数据变化的刷新频率
    41. * */
    42. sm.registerListener(myAccelerometerListener,sm.getDefaultSensor(sensorType),SensorManager.SENSOR_DELAY_NORMAL);
    43.
    44. }
    45.
    46. /*
    47. * SensorEventListener接口的实现,需要实现两个方法
    48. * 方法1 onSensorChanged 当数据变化的时候被触发调用
    49. * 方法2 onAccuracyChanged 当获得数据的精度发生变化的时候被调用,比如突然无法获得数据时
    50. * */
    51. final SensorEventListener myAccelerometerListener = new SensorEventListener(){
    52.
    53. //复写onSensorChanged方法
    54. public void onSensorChanged(SensorEvent sensorEvent){
    55. if(sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER){
    56. Log.i(TAG,”onSensorChanged”);
    57.
    58. //图解中已经解释三个值的含义
    59. float X_lateral = sensorEvent.values[0];
    60. float Y_longitudinal = sensorEvent.values[1];
    61. float Z_vertical = sensorEvent.values[2];
    62. Log.i(TAG,”\n heading “+X_lateral);
    63. Log.i(TAG,”\n pitch “+Y_longitudinal);
    64. Log.i(TAG,”\n roll “+Z_vertical);
    65. }
    66. }
    67. //复写onAccuracyChanged方法
    68. public void onAccuracyChanged(Sensor sensor , int accuracy){
    69. Log.i(TAG, “onAccuracyChanged”);
    70. }
    71. };
    72.
    73. public void onPause(){
    74. /*
    75. * 很关键的部分:注意,说明文档中提到,即使activity不可见的时候,感应器依然会继续的工作,测试的时候可以发现,没有正常的刷新频率
    76. * 也会非常高,所以一定要在onPause方法中关闭触发器,否则讲耗费用户大量电量,很不负责。
    77. * */
    78. sm.unregisterListener(myAccelerometerListener);
    79. super.onPause();
    80. }
    81.
    82.}

    测试的时候会发现刷新的特别快,这就引出一个问题,如果真的要呈现在UI中的话,就会不断的绘制界面,非常耗费资源,所以《android高级编程》中给出了一个方案就是引入新的线程来刷新界面。

    (2)获取用户移动方向

    其实获取方向本应该很简单的事情,在文章前面部分看到 有个TYPE_ORIENTATION 关键字,说明可以直接获取设备的移动方向,但是最新版的SDK加上了这么一句话“TYPE_ORIENTATION This constant is deprecated. use SensorManager.getOrientation() instead. ”也就是说,这种方式已经被取消,要开发者使用 SensorManager.getOrientation()来获取原来的数据。

    实际上,android获取方向是通过磁场感应器和加速度感应器共同获得的,至于具体的算法SDK已经封装好了。也就是说现在获取用户方向有两种方式,一是官方推荐的,通过SensorManager.getOrientation()来获取,这个方法表面看似容易(那是因为你还没看到他的参数。。一会再说),但实际上需要用到两个感应器共同完成工作,特点是更加的准确。第二种方法非常简单,就像前一篇文章获取加速度一样,直接得到三个轴上的数据。从难一些的介绍吧,因为毕竟第一种方法会是android未来的一个选择,第二种不知道什么时候就要成为历史了。

    android给我们提供的方向数据是一个float型的数组,包含三个方向的值如图

    当你的手机水平放置时,被默认为静置状态,即XY角度均为0

    values[0] 表示Z轴的角度:方向角,我们平时判断的东西南北就是看这个数据的,经过我的实验,发现了一个有意思的事情,也就是说使用第一种方式获得方向(磁场+加速度)得到的数据范围是(-180~180),也就是说,0表示正北,90表示正东,180/-180表示正南,-90表示正西。而第二种方式(直接通过方向感应器)数据范围是(0~360)360/0表示正北,90表示正东,180表示正南,270表示正西。

    values[1] 表示X轴的角度:俯仰角 即由静止状态开始,前后翻转

    values[2] 表示Y轴的角度:翻转角 即由静止状态开始,左右翻转

    可见统一获取方向的方法是必须的,因为处理这些数据的算法可能针对第一种获取方式,那么当用在第二种方式时,移植性就不好了。

    看下面的方法


    public static float[] getOrientation(float[] R, float[] values)

    Since: API Level 3

    Computes the device’s orientation based on the rotation matrix.

    When it returns, the array values is filled with the result:

    •values[0]: azimuth, rotation around the Z axis.

    •values[1]: pitch, rotation around the X axis.

    •values[2]: roll, rotation around the Y axis.

    The reference coordinate-system used is different from the world coordinate-system defined for the rotation matrix:

    •X is defined as the vector product Y.Z(It is tangential to the ground at the device’s current location and roughly points West).

    •Y is tangential to the ground at the device’s current location and points towards the magnetic North Pole.

    •Z points towards the center of the Earth and is perpendicular to the ground.

    All three angles above are in radiansand positivein the counter-clockwisedirection.

    通常我们并不需要获取这个函数的返回值,这个方法会根据参数R[]的数据填充values[]而后者就是我们想要的。

    那么R表示什么呢?又将怎么获取呢?

    R[] 是一个旋转矩阵,用来保存磁场和加速度的数据,大家可以理解未加工的方向数据吧

    R通过下面的静态方法获取,这个方法也是用来填充R[]

    public static boolean getRotationMatrix(float[] R, float[] I, float[] gravity, float[] geomagnetic)

    解释以下参数,第一个就是我们需要填充的R数组,大小是9

    第二个是是一个转换矩阵,将磁场数据转换进实际的重力坐标中 一般默认情况下可以设置为null

    第三个是一个大小为3的数组,表示从加速度感应器获取来的数据 在onSensorChanged中

    第四个是一个大小为3的数组,表示从磁场感应器获取来的数据 在onSensorChanged中

    好了基本逻辑就是这样的,下面给大家演示一个简单的测试方向的例子,可以时刻监听用户的方向

    1./*
    2. * @author octobershiner
    3. * 2011 07 28
    4. * SE.HIT
    5. * 一个演示通过磁场和加速度两个感应器获取方向数据的例子
    6. * */
    7.
    8.
    9.package uni.sensor;
    10.
    11.import android.app.Activity;
    12.import android.content.Context;
    13.import android.hardware.Sensor;
    14.import android.hardware.SensorEvent;
    15.import android.hardware.SensorEventListener;
    16.import android.hardware.SensorManager;
    17.import android.os.Bundle;
    18.import android.util.Log;
    19.
    20.public class OrientationActivity extends Activity{
    21.
    22. private SensorManager sm;
    23. //需要两个Sensor
    24. private Sensor aSensor;
    25. private Sensor mSensor;
    26.
    27. float[] accelerometerValues = new float[3];
    28. float[] magneticFieldValues = new float[3];
    29.
    30. private static final String TAG = “sensor”;
    31.
    32. @Override
    33. public void onCreate(Bundle savedInstanceState) {
    34. // TODO Auto-generated method stub
    35. super.onCreate(savedInstanceState);
    36. setContentView(R.layout.main);
    37.
    38. sm = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
    39. aSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    40. mSensor = sm.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
    41.
    42. sm.registerListener(myListener, aSensor, SensorManager.SENSOR_DELAY_NORMAL);
    43. sm.registerListener(myListener, mSensor,SensorManager.SENSOR_DELAY_NORMAL);
    44. //更新显示数据的方法
    45. calculateOrientation();
    46.
    47. }
    48. //再次强调:注意activity暂停的时候释放
    49. public void onPause(){
    50. sm.unregisterListener(myListener);
    51. super.onPause();
    52. }
    53.
    54.
    55. final SensorEventListener myListener = new SensorEventListener() {
    56. public void onSensorChanged(SensorEvent sensorEvent) {
    57.
    58. if (sensorEvent.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
    59. magneticFieldValues = sensorEvent.values;
    60. if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
    61. accelerometerValues = sensorEvent.values;
    62. calculateOrientation();
    63. }
    64. public void onAccuracyChanged(Sensor sensor, int accuracy) {}
    65. };
    66.
    67.
    68. private void calculateOrientation() {
    69. float[] values = new float[3];
    70. float[] R = new float[9];
    71. SensorManager.getRotationMatrix(R, null, accelerometerValues, magneticFieldValues);
    72. SensorManager.getOrientation(R, values);
    73.
    74. // 要经过一次数据格式的转换,转换为度
    75. values[0] = (float) Math.toDegrees(values[0]);
    76. Log.i(TAG, values[0]+”“);
    77. //values[1] = (float) Math.toDegrees(values[1]);
    78. //values[2] = (float) Math.toDegrees(values[2]);
    79.
    80. if(values[0] >= -5 && values[0] < 5){
    81. Log.i(TAG, “正北”);
    82. }
    83. else if(values[0] >= 5 && values[0] < 85){
    84. Log.i(TAG, “东北”);
    85. }
    86. else if(values[0] >= 85 && values[0] <=95){
    87. Log.i(TAG, “正东”);
    88. }
    89. else if(values[0] >= 95 && values[0] <175){
    90. Log.i(TAG, “东南”);
    91. }
    92. else if((values[0] >= 175 && values[0] <= 180) || (values[0]) >= -180 && values[0] < -175){
    93. Log.i(TAG, “正南”);
    94. }
    95. else if(values[0] >= -175 && values[0] <-95){
    96. Log.i(TAG, “西南”);
    97. }
    98. else if(values[0] >= -95 && values[0] < -85){
    99. Log.i(TAG, “正西”);
    100. }
    101. else if(values[0] >= -85 && values[0] <-5){
    102. Log.i(TAG, “西北”);
    103. }
    104. }
    105.
    106.
    107.}

    第二种方法,和这种比起来简单很多,其实大家可以完全参考获取加速度例子中的代码

    只要把其中的两个Sensor。TYPE_ACCELEROMETER改成 Sensor.TYPE_ORIENTATIO就好了,但是第一种方法大家最好掌握,这应该是未来android的标准。

    展开全文
  • 所能搜索到的资料特别的少,但恰恰接到了一个这样的需求,使用android平板通过USB与一个外接设备进行通讯,这个设备是一个压力感应器,在压力发生变化时可以测到相应的压力值,Android设备通过USB对设备进行供电并与...

            关于Android与USB设备的连接,所能搜索到的资料特别的少,但恰恰接到了一个这样的需求,使用android平板通过USB与一个外接设备进行通讯,这个设备是一个压力感应器,在压力发生变化时可以测到相应的压力值,Android设备通过USB对设备进行供电并与该设备进行通讯,将测量到的数据读取下来并进行保存分析。这是一个典型的Android设备作为USBHost、外接设备作为USBDevice的Host Mode。关于Android所提供的USB连接模式,可以参考:http://developer.android.com/guide/topics/connectivity/usb/index.html,这里对两种连接模式都做了比较详细的介绍,不再赘述。下面主要针对我所遇到的问题做一些分析。

    首先看Host mode所需要用的的类:

    UsbManager:Allows you to enumerate and communicate with connected USB devices.字面含义就是允许你列举并与已连接的USB设备进行交互,其实就是一个USB管理器,可以通过它来获取已连接的USB Device列表。使用上很简单:UsbManager manager = (UsbManager) getSystemService(USB_SERVICE);就可以获取到一个实例。

    USBDevice:Represents a connected USB device and contains methods to access its identifying information, interfaces, and endpoints.表示一个已连接的USB设备,包含获取它的识别信息、接口和端点的方法。获取一个USBDevice列表的方法:HashMap<String, UsbDevice> devices = um.getDeviceList();。

    UsbInterface:Represents an interface of a USB device, which defines a set of functionality for the device. A device can have one or more interfaces on which to communicate on.表示一个为该设备定义了一个函数集的USB设备接口。一个设备可以拥有一个或多个用来交互的接口。获取一个设备的接口数量:int interfaceCount = device.getInterfaceCount();,如果使用index为0的interface则可以:UsbInterface ui = device.getInterface(0); 。

    UsbEndpoint:Represents an interface endpoint, which is a communication channel for this interface. An interface can have one or more endpoints, and usually has input and output endpoints for two-way communication with the device. 表示一个接口端点,该端点作为这个接口的一个交互channel,一个接口可以拥有一个或多个端点,通常有输入和输出端点为一个设备提供两种交互方式。

    UsbDeviceConnection:Represents a connection to the device, which transfers data on endpoints. This class allows you to send data back and forth sychronously or asynchronously.表示在通过端点与设备传输数据的一个连接,该类允许你同步或异步的发送信息出去或者回来。

    在获取一个UsbEndpoint时,务必要执行conn.claimInterface(UsbInterface intf, boolean force)方法。在使用中

    if(!um.hasPermission(device)){//判断是否拥有该设备的连接权限,如果没有则请求权限
        um.requestPermission(device, this.createPendingResult(0, null, 0));
    }

    if(manager.hasPermission(device)){//如果已经拥有该设备的连接权限
        conn = manager.openDevice(device);//打开一个UsbDeviceConnection
    }

    if(conn==null){
          Toast.makeText(this, "USB设备连接不可用!", Toast.LENGTH_SHORT).show();
          return false;
    }
    if(conn.claimInterface(ui, true)){//This must be done before sending or receiving data on any UsbEndpoints belonging to the interface.
          point = ui.getEndpoint(1);
          dataPoint = ui.getEndpoint(0);
          return true;
     }

    如果配置正确的话,通过上面的几个类,应该可以成功的获得了一个可用的UsbEndpoint。

    但需要注意的是,这时需要声明USB设备的信息,

    <?xml version="1.0" encoding="utf-8"?>

    <resources>

         <usb-devicevendor-id="1234"product-id="5678"class="255"subclass="66"protocol="1"/>

    </resources>

    具体的这些id需要根据所连接的设备而有所不同,这个资源文件必须声明在res/xml/device_filter.xml中

    完成这个声明以后,一般的,在USB设备接入时,系统如果检测到该设备,如果此时需要提示则应该

    <manifest ...>

         <uses-featureandroid:name="android.hardware.usb.host"/>

         <uses-sdkandroid:minSdkVersion="12"/>

        ... <application>

            <activity ...> ...

                <intent-filter>

                    <actionandroid:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"/>

                </intent-filter>

                <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"android:resource="@xml/device_filter"/>

            </activity>

        </application>

    </manifest>

    表示,在device_filter文件中的声明的设备连接到Android设备时,会触发连接的提示。

    如果上面的连接正常,那么就可以与设备进行数据的传输了。

    一般地,都会启动一个线程来完成这项工作。

    request.initialize(conn, dataPoint);//初始化请求
    ByteBuffer bb =ByteBuffer.allocate(2);//数据接收的ByteBuffer,具体大小要根据不同的设备而有所不同
    while(canStop){
        request.queue(bb, 2);
        byte[] dst = new byte[2];
        int accessRes = conn.bulkTransfer(point, access, 2, 1000);//发送USB外设所能执行的命令
        if(accessRes<0){
            return;
        }
        if(request == conn.requestWait()){//请求完成,如果发生错误则方法返回null
            dst = bb.array();//返回的数据

        }

    }

    UsbRequest:Represents an asynchronous request to communicate with a device through aUsbDeviceConnection.表示通过一个UsbDeviceConnection实例与设备进行交互的一个异步请求。

    在这个数据传输的过程中,需要发送命令和接收数据,发送命令的方法有两个:

    controlTransfer(int requestType, int request, int value, int index, byte[] buffer, int length, int timeout)

    Performs a control transaction on endpoint zero for this device.
    参数requestType,该事务的请求类型,参数request,该事务的请求ID,参数value,该事务的值,参数index,该事务的索引,参数buffer,该事务的数据buffer,如果没有数据需要被发送或接收,可以为null,参数length,发送或接收数据的长度,参数timeout,超时时间,单位毫秒
    另外一个是,
    bulkTransfer(UsbEndpoint endpoint, byte[] buffer, int length, int timeout)
    Performs a bulk transaction on the given endpoint.
    参数endpoint,需要通过哪个端点来发送数据,参数buffer,要发送或接收的数据buffer,参数length,要发送或接收的数据长度,参数timeout,超时时间,单位毫秒
    如果返回值为负值,则说明失败,否则返回发送成功数据的长度。
    在发送完毕后,应当使用UsbDeviceConnection的requestWait()方法来等待响应获取返回的数据。
            至此,整个连接设备与数据交互的过程就可以算完成了,具体到发送什么样的命令,根据所连接设备的不同自然也是不同的,整个流程大致就如上面所说。Google也提供了一个Demo,如果没有下载的话可以在这里下载
    展开全文
  • Use getSensorList(int) to get the list of available Sensors.”,表示一个感应器的类,可以使用getSensorList方法(此方法属于接下来要讲的SensorManager)获得所有可用的感应器,该方法返回的是一个List ...

    介绍Sensor类

    SDK只有一句介绍“Class representing a sensor. Use getSensorList(int) to get the list of available Sensors.”,表示一个感应器的类,可以使用getSensorList方法(此方法属于接下来要讲的SensorManager)获得所有可用的感应器,该方法返回的是一个List
    下面的列表显示了,Sensor所提供的所有服务
    Constants
    int TYPE_ACCELEROMETER A constant describing an accelerometer sensor type.
    //三轴加速度感应器 返回三个坐标轴的加速度 单位m/s2
    int TYPE_ALL A constant describing all sensor types.
    //用于列出所有感应器
    int TYPE_GRAVITY A constant describing a gravity sensor type.
    //重力感应器
    int TYPE_GYROSCOPE A constant describing a gyroscope sensor type
    //陀螺仪 可判断方向 返回三个坐标轴上的角度
    int TYPE_LIGHT A constant describing an light sensor type.
    //光线感应器 单位 lux 勒克斯
    int TYPE_LINEAR_ACCELERATION A constant describing a linear acceleration sensor type.
    //线性加速度
    int TYPE_MAGNETIC_FIELD A constant describing a magnetic field sensor type.
    //磁场感应 返回三个坐标轴的数值 微特斯拉
    int TYPE_ORIENTATION This constant is deprecated. use SensorManager.getOrientation() instead.
    //方向感应器 已过时 可以使用方法获得
    int TYPE_PRESSURE A constant describing a pressure sensor type
    //压力感应器 单位 千帕斯卡
    int TYPE_PROXIMITY A constant describing an proximity sensor type.
    //距离传感器
    int TYPE_ROTATION_VECTOR A constant describing a rotation vector sensor type.
    //翻转传感器
    int TYPE_TEMPERATURE A constant describing a temperature sensor type
    //温度传感器 单位 摄氏度
    此类中包含的方法都是get型的 用来获取所选sensor的一些属性,sensor类一般不需要new而是通过SensorManager的方法获得

    加速度感应器

    可以通过这个感应器获得三个浮点型
    x-axis
    y-axis
    z-axis
    这里写图片描述

    X Y Z分别对应values[0]到[2]
    X表示左右移动的加速度
    Y表示前后移动的加速度
    Z表示垂直方向的加速度 (测试时发现,将手机置于水平桌面稳定后 XY均为0 Z的值为9.4 约等于重力加速度,依次可以做一个简单的算法实现重力测力计。)

    //申请震动权限
    <uses-permission android:name="android.permission.VIBRATE"/>
    
    package com.zingon.ztc.gpstry;
    
    import android.content.Context;
    import android.hardware.SensorManager;
    import android.location.LocationManager;
    import android.os.Bundle;
    import android.os.Vibrator;
    import android.support.v7.app.AppCompatActivity;
    import android.widget.TextView;
    
    public class MainActivity extends AppCompatActivity {
    
        TextView inf;
        //感应器管理器,所有感应器都可以通过它获得
        SensorManager sm;
        //震动
        Vibrator vb;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            inf=(TextView)findViewById(R.id.inf);
            //获得系统服务
            sm= (SensorManager) getSystemService(Context.SENSOR_SERVICE);
            vb= (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
            new SensorTry(sm,inf,vb).run();
        }
    }
    package com.zingon.ztc.gpstry;
    
    import android.hardware.Sensor;
    import android.hardware.SensorEvent;
    import android.hardware.SensorEventListener;
    import android.hardware.SensorManager;
    import android.os.Vibrator;
    import android.util.Log;
    import android.widget.TextView;
    
    /**
     * Created by ztc on 16-3-9.
     */
    public class SensorTry extends Thread{
        SensorManager sm;
        String TAG = "sensor";
        TextView inf;
        Vibrator vb;
        float x,y,z;
        public SensorTry(SensorManager sm,TextView inf,Vibrator vb){
            this.sm=sm;
            this.inf=inf;
            this.vb=vb;
        }
    
        @Override
        public void run() {
        //获得加速度传感器
            Sensor sensor=sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
            //注册监听器
            sm.registerListener(myListener, sensor, SensorManager.SENSOR_DELAY_NORMAL);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
        }
        //监听器
        SensorEventListener myListener=new SensorEventListener() {
            @Override
            public void onSensorChanged(SensorEvent event) {
                if(event.sensor.getType()==Sensor.TYPE_ACCELEROMETER){
    
                    //图解中已经解释三个值的含义
                    //当值变化超过 1 时,震动
                    if(Math.abs(x-event.values[0])>=1||Math.abs(y-event.values[1])>=1||Math.abs(z-event.values[2])>=1) {
                        x = event.values[0];
                        y = event.values[1];
                        z = event.values[2];
                        Log.i(TAG,"onSensorChanged");
                        Log.i(TAG, "\n heading " + x);
                        Log.i(TAG, "\n pitch " + y);
                        Log.i(TAG, "\n roll " + z);
                        inf.setText("设备重力传感器\n\nX:");
                        inf.append(String.valueOf((int) x));
                        inf.append("\nY:");
                        inf.append(String.valueOf((int) y));
                        inf.append("\nZ:");
                        inf.append(String.valueOf((int) z));
                        // 停止 开启 停止 开启
                        long[] pattern = {100, 400, 100, 400};
                        vb.vibrate(pattern, -1);
                    }
                }
    
            }
    
            @Override
            public void onAccuracyChanged(Sensor sensor, int accuracy) {
                Log.i(TAG, "onAccuracyChanged");
            }
        };
    }

    效果

    手机移动,就会震动
    
    展开全文
  • 目前android 从基本的WIFI, GPS, 到加速度感应器,应用无处不在。   。 传感器名称如下: 加速度传感器(accelerometer) 陀螺仪传感器(gyroscope) 环境光照传感器(light) 磁力传感器(magnetic field) 方向传感器...
  • Shortcut概念具体实现 ...Shortcut 是Android-25(Android 7.1)新增的一项类似iOS的 3D Touch 功能的快捷方式组件,但是有着不同的表现形式,因为Android在硬件上不支持触摸压力感应,所以表现形式为长按,而
  • 基于感应器的智能求救系统----以android为例实现 基于感应器的智能求救系统是由android实验小组研发的一款基于android手机系统以及汽车硬件的能够通过感应外界温度、压力、初速度就可以轻松求救及手机寻回的软件。...
  • android传感器sensor

    2015-09-08 21:58:25
    HAL层的头文件代码位于hardware\libhardware\include\hardware\sensors.h。 HAL层支持13种类型的传感器:/** * Sensor types */ #define SENSOR_TYPE_ACCELEROMETER 1 #define SENSOR_TYPE_MAGNETIC_FIELD 2 ...
  • Android 8.0 新特性

    2017-11-13 15:05:12
    Android 8.0 新特性前言Android 8.0 是目前 Android 最新的智能手机操作系统,2017年3月21日 Google 为开发者推出了新的 Android O 首个开发者预览版,2017 Google I/O 开发者大会上发布了第二个Android O开发者预览...
  • 接上文《Android那些事儿 成长中的Android 》。本文描述了与其它触屏手机系统和桌面系统不同的Android平台特性,这些特性需要更多的表现在我们开发的应用程序中,以保证这是一款Android手机的应用。这些特性可能对于...
  • 最近学习了下传感器的操作,但很多书籍都直接讲怎么取值,没有讲清楚怎么分辨不同类型传感器XYZ坐标方向的问题,小马这篇文章主要来说下方向的分辨及小工具实现模拟真机传感器的访问,因为小马在方向感上很YUN.......
  • 下载地址 最后更新共计113个分类5177套源码29.2 GB。...│ │ Android TagCloudView云标签的灵活运用.rar │ │ Android 实现 标签 拖动 改变位置.rar │ │ android 流式布局和热门标签.zip │ │ ...
  • 本文节选于机械工业出版社推出的《Android应用开发揭秘》一书。内容为第九章9.1传感器和9.2语音识别两个部分。第9章 Android特色开发Android 是一个面向应用程序开发的丰富平台,它拥有许多具有吸引力的用户界面元素...
  • 昨天在写音乐播放器,想给它加个重力感应甩歌功能,到网上找了个Demo(搜索了好久,找到N个,结果都是转载一个),结果发现却无法运行,打开就报错。今天仔细看了下代码,稍做了下修改,发现可以运行了。抄一下原文...
  • 目录第一章 Android 操作系统概述Android 软件架构介绍(五层架构)(填空题)Android的子系统Android 应用程序开发过程(2种形式的开发,开发过程)第二章 Android 源码开发环境搭建Android源码开发环境搭建步骤...
  • 传感器(Sensor)系统可以让智能手机的功能更加丰富多彩,在Android系统中支持多种传感器。Android的Sensor系统涉及了Android的各个层次。Android系统支持多种传感器,有的传感器已经在Android的框架中使用,大多数...
  • android平台框架原理

    2016-07-13 09:20:21
    1.理解两个概念 抽象和...用户操作一个软件的时候,其实中间还隔了一层,那就是系统,例如,用户点击了屏幕上的一个按钮,就会对屏幕产生物理感应,屏幕将这种物理感应交给系统os处理,系统产生相应的事件对象,交给框
  • Android常用代码速查

    2019-12-24 08:01:31
    原文地址:... 0 android 创建按钮 Button button = new Button(this); 1 android 创建输入框 EditText editText = new EditText(this); 2 android 创建文本 TextVi...
1 2 3 4 5 ... 20
收藏数 510
精华内容 204