Android 传感器(Sensor)API教程

来源:互联网 发布:淘宝上买药怎么付款 编辑:程序博客网 时间:2024/05/07 00:36
帖地址:http://www.androidegg.com/portal.php?mod=view&aid=578 谢谢原作者的分享

摘要: 主要介绍传感器的种类,常用方法,事件等,通过例程进行讲解分析。传感器(Sensor)听起来似乎感觉很难,其实它并不是很难。做起来并很有意思的,我相信,通过我对传感器的介绍你会对它感兴趣的,应为你可以切身体会到 ...

1.1 序言   
     在这一章我们主要针对Android的传感器(Sensor)进行说明。如果说Java的程序和硬件有些远的感觉,那么可以说传感器距离硬件很近。传感器(Sensor)听起来似乎感觉很难,其实它并不是很难。做起来并很有意思的,我相信,通过我对传感器的介绍你会对它感兴趣的,应为你可以切身体会到它的存在。

1.2 传感器(Sensor)是什么?
    传感器是能标识温度,加速度等等物理现象的转换电子信号的机器。Android SDK,在移动设备中提供了各种各样的传感器的API。那么,本章的例程,在模拟器中不能使用,这点请大家注意。需要在实际的手机上测试才能体现。这里我就不进行详细进行说明如何连接手机进行运行程序了,在本网站 【Android蛋蛋网】有对应的介绍,请读者自己参照。

1.3  传感器(Sensor)关联的类(Class)和接口(Interface)
     首先,我们对Android SDK提供的传感器关联的类和接口进行介绍。
1.3.1  android.hardware.Sensor类
   
Sensor类,是管理各种传感器的共同属性(名字,版本等等)的类。


●主要的常量
     
在Sensor类,能使用的传感器的种类通过常量来定义的(表1-1)。但是根据硬件,传感器搭载是任意的。比如现在市场销售的(Dev Phone,HTC Dream)实际确认有
TYPE_ACCELEROMETER,
TYPE_ORIENTATION,
TYPE_MAGNETIC_FIELD,
TYPE_TEMPERATURE
四种类别。

表1-1 传感器的种类

常量名
说明
实际的值
TYPE_ACCELEROMETER
加速度
1
TYPE_GYROSCOPE
陀螺仪
4
TYPE_LIGHT
光照
5
TYPE_MAGNETIC_FIELD
磁力计
2
TYPE_ORIENTATION
方位传感器
3
TYPE_PRESSURE
压力传感器
6
TYPE_PROXIMITY
距离传感器
8
TYPE_TEMPERATURE
温度传感器
7
TYPE_ALL
全部的传感器
-1

●主要的方法
     Sensor类的主要的方法参照下面的表1-2

方法
处理内容
public float getMaximumRange()
返回传感器的最大值
public String getName()
返回传感器的名字
public float getPower()
f返回传感器的功率(mA毫安)
public float getResolution()
返回传感器的精度
public int getType()
返回传感器的类型
public String getVentor()
返回Vendor名
public int getVersion()
返回传感器的版本号

1.3.2  android.hardware.SensorManager类
  
SensorManager类是对搭载的移动设备的传感器进行访问的类,用这个类的借口能取得事件监听器的登录/删除、传感器的信息。

●主要的常量
    
在SensorManager有很多个常量被定义,但是这些中最重要的是关于传感器的反应速度的,如(表1-3)。Android,在监听器进行登录的时候通过4个阶段对传感器进行设定的。
表1-3 关于传感器的反映速度的常量

常量名
说明
实际的值
SENSOR_DELAY_FASTEST
在游戏想特别快的反应速度的时候使用
0
SENSOR_DELAY_GAME
游戏用
1
SENSOR_DELAY_UI
用户接口用
2
SENSOR_DELAY_NORMAL
取得倾斜度的时候使用(缺省)
3

●主要的方法
     
SensorManager类的主要方法如表1-4所示
表1-4 SensorManager类的主要方法 
方法
处理内容
public boolean registerListener(
      SensorEventListener listener,
      Sensor sensor,
      int rate)
登录被指定反应速度的监听器。反应速度的指定,使用前面的(表1-3)的SENSOR_DELAY系列常量
public void unregisterListener(SensorEventListener listener)
解除全部的传感器的监听器的登录
public voidunregisterListener(SensorEventListener listener,
         Sensor sensor)
解除在sensor被指定的监听器的登录
public List getSensorLIst(int type)
用list形式取得能使用的传感器的接口


1.3.3  SensorManager类的Instance取得例程
  
 
SensorManager不能直接生成Instance。SensorManager的Instance是通过Context类定义的getSystemService方法取得的。在图1-1的Activity,SensorManager的Instance取得,传感器的名字取得,具体代码如下。

图1-1  传感器的信息取得例程

AndroidEggSensorActivity.java

package androidegg.stu.sensor;

import java.util.List;

import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.widget.TextView;

public class AndroidEggSensorActivity extends Activity implements SensorEventListener{
    /** Called when the activity is first created. */
    //SensorManager instance
    private SensorManager sensorManager;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //get SensorManager instance
        sensorManager = (SensorManager)this.getSystemService(SENSOR_SERVICE);
        setContentView(R.layout.main);
    }
    
    @Override
    protected void onResume(){
        super.onResume();
        List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
        LinearLayout layout = new LinearLayout(this);
        layout.setOrientation(LinearLayout.VERTICAL);
        TextView tv;
        for (Sensor s:sensors){
            tv = new TextView(this);
            tv.setText(s.getName());
            layout.addView(tv,new LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.FILL_PARENT,
                    LinearLayout.LayoutParams.WRAP_CONTENT));
        }
        setContentView(layout);
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        // TODO Auto-generated method stub
        
    }
}

重要点如下所示
1 在onCreate 方法中取得
SensorManager的Instance
2 在onResume 方法中取得传感器的名字,并表示

1.3.4  android.hardware.SensorEvent 

     SensorEvent类是在传感器事件(onAccuracyChanged  , onSensorChanged 稍后介绍)为了对能取得的信息进行整理管理的类。被管理的值全部用公用的field定义的。

●主要的字段(field)
SensorEvent类的主要的field如表1-5所示
                              表1-5    SensorEvent类的主要的field

字段(field)
内容
public int accuracy
传感器的精度
public Sensor sensor
传感器的instance
public long timestamp
时间(毫微秒)
public final flaot[] values
传感器的值

    1.3.5  android.hardware.SensorEventListener接口
   
SensorEventListener接口是为了取得传感器的事件的事件监听器。前面所说的
SensorManager类具有登录删除功能。在这个封装的接口中可以取得传感器的值。

●主要的事件
方法
处理内容
void onAccuracyChanged(Sensor sensor,int accuracy)
传感器的精度变化的时候,此方法被调用
void onSensorChanged(SensorEvent event)
传感器的值改变的时候,此方法被调用


1.3.6  传感器的值取得及例程
      传感器值取得需要通过SensorManager#registerListener方法对加载SensorEventListener接口的对象进行登录处理。从登录监听器开始到传感器的值取得的动作处理过程如图1-2那样所示。在程序列表1-2中的传感器的值取得,画面处理结果(图1-3)所示。
    

  图1-3 传感器值取得例程运行结果

  程序列表1-2 传感器的值取得画面输出例程

package androidegg.stu.sensor;

import java.util.List;
import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.widget.TextView;

public class AndroidEggSensorGetValueActivity extends Activity implements SensorEventListener{    //...①
    /** Called when the activity is first created. */
    private SensorManager sensorManager;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //SensorManager的接口取得
        sensorManager = (SensorManager)this.getSystemService(SENSOR_SERVICE);
        setContentView(R.layout.main);
    }
    
    @Override
    protected void onResume(){                                                //...②
        super.onResume();
        List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
        
        //sensor1
        for (Sensor s : sensors){
            sensorManager.registerListener(this,s,SensorManager.SENSOR_DELAY_NORMAL);
        }              
    }
    
    //
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void onSensorChanged(SensorEvent e) {                                   //...③
        // TODO Auto-generated method stub
        switch(e.sensor.getType()){
            //加速度的值表示
            case Sensor.TYPE_ACCELEROMETER:{
                TextView x = (TextView)findViewById(R.id.x);
                x.setText("x:" + String.valueOf(e.values[SensorManager.DATA_X]));
                TextView y = (TextView)findViewById(R.id.y);
                y.setText("y:" + String.valueOf(e.values[SensorManager.DATA_Y]));
                TextView z =(TextView)findViewById(R.id.z);
                z.setText("z:" + String.valueOf(e.values[SensorManager.DATA_Z]));
                break;
            }
            //倾斜度的值表示
            case Sensor.TYPE_ORIENTATION:{
                TextView x = (TextView)findViewById(R.id.Azimuth);
                x.setText("Azimuth" + String.valueOf(e.values[SensorManager.DATA_X]));
                
                TextView y = (TextView)findViewById(R.id.Pitch);
                y.setText("Pitch:" + String.valueOf(e.values[SensorManager.DATA_Y]));
                
                TextView z = (TextView)findViewById(R.id.Roll);
                z.setText("Roll:" + String.valueOf(e.values[SensorManager.DATA_Z]));
                break;
            }
            //磁力计 的值表示
            case Sensor.TYPE_MAGNETIC_FIELD:{
                TextView x = (TextView)findViewById(R.id.magnetic_x);
                x.setText("x:" + String.valueOf(e.values[SensorManager.DATA_X]));
                TextView y = (TextView)findViewById(R.id.magnetic_y);
                y.setText("y:" + String.valueOf(e.values[SensorManager.DATA_Y]));
                
                TextView z= (TextView)findViewById(R.id.magnetic_z);
                z.setText("z:" + String.valueOf(e.values[SensorManager.DATA_Z]));
                break;
            }
            //温度計の値を表示する
            case Sensor.TYPE_TEMPERATURE:{
                TextView x = (TextView)findViewById(R.id.degree);
                x.setText("Degree:" + String.valueOf(e.values[SensorManager.DATA_X]));
            }
        }
    
    }  
    //
    @Override
    protected void onStop(){
        super.onStop();                                                      //...④
        sensorManager.unregisterListener(this);
    }
}

重要事项如下所示
① 为了取得传感器的值,需要加载SensorEventListener
② 在onResume方法进行监听器的登录
③ 在onSensorChanged方法中取得传感器的值,并在画面表示。
     在这个方法中在onResume方法中登录的所有种类的传感器的值都可以取道。判别传感器的种类,将传感器的值用
     TextView在画面表示出来。
④ 在onStop方法中接触所有登录的监听器。

传感器值取得例程 说明
您需要登录才可以下载或查看附件
文件名称
AndroidEgg SensorGetValue.zip 
文件大小
43.3 KB
文件格式
zip
下载

AndroidEgg SensorGetValue.zip

1.4 加速度传感器
    加速度传感器是为了检测物体的加速度的传感器。物体运动加速度也跟着变化,如果能取到加速度,物体受到什么样的作用力或则物体进行什么样的运动,我们就可以知道。使用加速度,我们就能做模拟计步器、物体运动的应用程序。
1.4.1  通过加速度传感器能取到的值
  
我们可以通过Android的加速度传感器可以取得x,y,z三个轴的加速度(如图1-4)。
   加速度值受地球重力的影响值也不一样。这就涉及到物理知识了,我就不细阐述了。也不是一句两句能说清楚的。在SensorManager类中定义了很多星体的重力加速度值。如表1-7
   

   图 1-4 加速度传感器的轴
表1-7 SensorManager 类被定义的各新星体的重力加速度值

常量名
说明
实际的值
GRAVITY_DEATH_STAR_1
死亡星
3.5303614E-7
GRAVITY_EARTH
地球
9.80665
GRAVITY_JUPITER
木星
23.12
GRAVITY_MARS
火星
3.71
GRAVITY_MERCURY
水星
3.7
GRAVITY_MOON
月亮
1.6
GRAVITY_NEPTUNE
海王星
11.0
GRAVITY_PLUTO
冥王星
0.6
GRAVITY_SATURN
土星
8.96
GRAVITY_SUN
太阳
275.0
GRAVITY_THE_ISLAND
岛屿星
4.815162
GRAVITY_URANUS
天王星
8.69
GRAVITY_VENUS
金星
8.87

1.4.2  只想保留重力的影响的时候
    
通常,从加速度传感器取得的值,拿手机手机设备的人的手震动或则放在摇晃的场所的时候,受震动影响设备的值增幅变化是存在的。手的摇动、轻微震动的影响是属于长波形式,去掉这种长波干扰的影响,可以取得高精度的值。去掉这种长波这种过滤机能叫
Low-Pass Filter。
    Low-Pass Filter的封装方法如下面所述。

         ・从抽样数据中取得中间的值的方法
         
最近取得的加速度的值每个很少变化的方法

     ●从抽样数据中取得中间的值的方法  
     从抽样数据取得中间值的抽样代码如下 列表1-3所示。并且,抽样数为30来做的,根据封装的程序的用途和传感器的感度进行调整。
       列表1-3 从抽样数据中取得中间值
package androidegg.stu.sensor;

import java.util.Arrays;
import java.util.List;

import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.widget.TextView;

public class AndroidEggSensorGetValueActivity extends Activity implements SensorEventListener{
    /** Called when the activity is first created. */
    private SensorManager sensorManager;
    private static final int ELEMENT_COUNT = 30;
    
    //Data
    private float[] samplingX = new float[ELEMENT_COUNT];      //..................①
    private float[] samplingY = new float[ELEMENT_COUNT];
    private float[] samplingZ = new float[ELEMENT_COUNT];
    
    private int position;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //SensorManagerのインスタンスを取得
        sensorManager = (SensorManager)this.getSystemService(SENSOR_SERVICE);
        setContentView(R.layout.main);
    }
    
    @Override
    protected void onResume(){
        super.onResume();
        List sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
        
        //sensor1
        for (Sensor s : sensors){
            sensorManager.registerListener(this,s,SensorManager.SENSOR_DELAY_NORMAL);
        }              
    }
    
    //
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void onSensorChanged(SensorEvent e) {
        if (position == ELEMENT_COUNT - 1){                                         
//..................②
            position =0;
        }else{
            position++;
        }
        float x = e.values[sensorManager.DATA_X];
        float y = e.values[sensorManager.DATA_Y];
        float z = e.values[sensorManager.DATA_Z];
        
        samplingX[position] = x;
        samplingY[position] = y;
        samplingZ[position] = z;
        
        TextView textX = (TextView)findViewById(R.id.x);
        textX.setText("x:" + String.valueOf(getMedian(samplingX)));
        TextView textY = (TextView)findViewById(R.id.y);
        textY.setText("y:" + String.valueOf(getMedian(samplingY)));
        TextView textZ = (TextView)findViewById(R.id.z);
        textZ.setText("Z:" + String.valueOf(getMedian(samplingZ)));
    }  
    
    private float getMedian(float[] values) {         
//..................③
        // TODO Auto-generated method stub
        float[] tmp = values.clone();
        Arrays.sort(tmp);
        int len = tmp.length;
        int first = 0;
        
        for (int i =0;i
            first =i;
        }
        return tmp[(len - first)/2 + first];
    }

    //
    @Override
    protected void onStop(){
        super.onStop();
        sensorManager.unregisterListener(this);
    }
}
         
运行结果如图1-5

重要注意点如下所示
     ①x,y,z 轴的各个保存用的数组定义
     ②抽样用的数据从数组的0开始的顺序保存,到第29个的时候再从0开始保存
     ③数组保存的值的中间值取得
最近取得的加速度的值每个很少变化的方法
   例程如列表1-4
       并且,在例程中取得的值增加10%,封装的应用程序要根据传感器的感应度进行调整。
      
       列表 1-4 
最近取得的加速度的值每个很少变化的方法的例程
package androidegg.stu.sensor;

import java.util.Arrays;
import java.util.List;

import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.widget.TextView;

public class AndroidEggSensorGetValueActivity extends Activity implements SensorEventListener{
    /** Called when the activity is first created. */
    private SensorManager sensorManager;           

    //
    private  final float FILTERING_VALAUE = 0.1f;
    private float lowX,lowY,lowZ;                       
//..................①
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //SensorManagerのインスタンスを取得
        sensorManager = (SensorManager)this.getSystemService(SENSOR_SERVICE);
        setContentView(R.layout.main);
    }
    
    @Override
    protected void onResume(){
        super.onResume();
        List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
        
        //sensor1
        for (Sensor s : sensors){
            sensorManager.registerListener(this,s,SensorManager.SENSOR_DELAY_NORMAL);
        }              
    }
    
    //
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void onSensorChanged(SensorEvent e) {
        float x = e.values[sensorManager.DATA_X];
        float y = e.values[sensorManager.DATA_Y];
        float z = e.values[sensorManager.DATA_Z];
        
        //
        lowX = x * FILTERING_VALAUE + lowX * (1.0f - FILTERING_VALAUE);  
//..................②
        lowY = y * FILTERING_VALAUE + lowY * (1.0f - FILTERING_VALAUE);
        lowZ = z * FILTERING_VALAUE + lowZ * (1.0f - FILTERING_VALAUE);

        TextView textX = (TextView)findViewById(R.id.x);
        textX.setText("x:" + String.valueOf(lowX));
        TextView textY = (TextView)findViewById(R.id.y);
        textY.setText("y:" + String.valueOf(lowY));
        TextView textZ = (TextView)findViewById(R.id.z);
        textZ.setText("Z:" + String.valueOf(lowZ));
    }  
    


    //
    @Override
    protected void onStop(){
        super.onStop();
        sensorManager.unregisterListener(this);
    }
}

     
运行结果如图1-5-1

重要注意点如下所示
     ①Low-Pass Filter处理的值保存的变量的定义
     ②取得的传感器的值的10%加上上回取得的90%


1.4.3  瞬间加速度值的取得
    
例如类似计步器、作用力测定的应用开发的时候,很想检测出加速度急剧的变化。这个时候,
和Low-Pass Filter处理相反,去掉短周波的影响,这样可以取得数据。像这种去掉短周波的影响的过滤器叫做High-pass filter。
  
High-pass filter的处理方法,如下面的例程列表1-5 代码所示:

    
列表1-5 瞬间加速度值的取得
package androidegg.stu.sensor;

import java.util.Arrays;
import java.util.List;

import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.widget.TextView;

public class AndroidEggSensorGetValueActivity extends Activity implements SensorEventListener{
    /** Called when the activity is first created. */
    private SensorManager sensorManager;
    //
    private  final float FILTERING_VALAUE = 0.1f;
    private float lowX,lowY,lowZ;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //SensorManager
        sensorManager = (SensorManager)this.getSystemService(SENSOR_SERVICE);
        setContentView(R.layout.main);
    }
    
    @Override
    protected void onResume(){
        super.onResume();
        List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
        
        //sensor1
        for (Sensor s : sensors){
            sensorManager.registerListener(this,s,SensorManager.SENSOR_DELAY_NORMAL);
        }              
    }
    
    //
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void onSensorChanged(SensorEvent e) {
        float x = e.values[sensorManager.DATA_X];
        float y = e.values[sensorManager.DATA_Y];
        float z = e.values[sensorManager.DATA_Z];
        
        //Low-Pass Filter
        lowX = x * FILTERING_VALAUE + lowX * (1.0f - FILTERING_VALAUE);
        lowY = y * FILTERING_VALAUE + lowY * (1.0f - FILTERING_VALAUE);
        lowZ = z * FILTERING_VALAUE + lowZ * (1.0f - FILTERING_VALAUE);

        //High-pass filter
        float highX  = x -  lowX;
        float highY  = y -  lowY;
        float highZ  = z -  lowZ;
        
        //output
        TextView textX = (TextView)findViewById(R.id.x);
        textX.setText("x:" + String.valueOf(highX));
        TextView textY = (TextView)findViewById(R.id.y);
        textY.setText("y:" + String.valueOf(highY));
        TextView textZ = (TextView)findViewById(R.id.z);
        textZ.setText("Z:" + String.valueOf(highZ));
    }  
    


    //
    @Override
    protected void onStop(){
        super.onStop();
        sensorManager.unregisterListener(this);
    }
}

运行结果如图1-5-2


1.4.4  加速度传感器运用实例
    
在这里,我们对
Low-Pass Filter和High-pass filter实例进行说明。在实际的运用中在什么样的场合下如何使用这两个过滤器,通过例程我们进行很好的理解。程序列表1-6列表1-7是摇晃手机表示图片的应用程序的代码(运行结果如图1-6)。在这个例程中作成ShakeActivity类和管理抽样数据的ValueHolder类。ShakeActivity类和ValueHolder类的关系如图1-7所示。
     

 图1-6 摇动手机并表示图片的例程

列表1-6 摇动手机并表示图片的例程1

package com.mamezou.android.shake;

import java.util.Arrays;

public class ValueHolder {                    
//..................①
  private static final float BLANK = -999;
  private int size;
  private float[] values;
  private int position = 0;
  public ValueHolder(int size) {
    this.size = size;
    values = new float[size];
    clear();
  }
  private void clear() {
    Arrays.fill(values, BLANK);
  }
  public boolean add(float value) {
    values[position] = value;
    if(size -1 == position) {
      position = 0;
      return true;
    } 
    position ++;
    return false;
  }
  // 取得中间值的方法
  public float getMedian() {                    
//..................②
    float[] tmp = values.clone();
    Arrays.sort(tmp);
    int len = tmp.length;
    int first = 0;
    for (int i = 0; i < len; i++) {
      first = i;
      if(tmp[i] != BLANK) break;
    }
    return tmp[(len - first) / 2 + first];
  }
}

要点如下所示

ValueHolder类管理用size指定的抽样数据

②返回保存的抽样数据的中间值。


列表1-6 摇动手机并表示图片的例程2

package com.mamezou.android.shake;

import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.BitmapDrawable;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.View;

public class ShakeActivity extends Activity implements SensorEventListener {
  private SensorManager sensorManager;
  private ValueHolder x;
  private ValueHolder y;
  private ValueHolder z;
  private View layout;
  // Android君的画像
  private BitmapDrawable andy;
  
  private static final int ELEMENT_COUNT = 30;
  
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
    layout = (View) findViewById(R.id.layout);
    andy = (BitmapDrawable) getResources().getDrawable(R.drawable.andy);
  }
  @Override
  protected void onResume() {
    super.onResume();
    sensorManager.registerListener(this,
    sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
        SensorManager.SENSOR_DELAY_FASTEST);
    x = new ValueHolder(ELEMENT_COUNT);
    y = new ValueHolder(ELEMENT_COUNT);
    z = new ValueHolder(ELEMENT_COUNT);
  }
  @Override
  protected void onStop() {
    sensorManager.unregisterListener(this);
    super.onStop();
  }
  public void onAccuracyChanged(Sensor sensor, int accuracy) {
  }
  public void onSensorChanged(SensorEvent e) {
    float sensorValueX = e.values[SensorManager.DATA_X];
    float sensorValueY = e.values[SensorManager.DATA_Y];
    float sensorValueZ = e.values[SensorManager.DATA_Z];
    x.add(sensorValueX);
    y.add(sensorValueY);
    z.add(sensorValueZ);
    float valueX = sensorValueX - x.getMedian();
    float valueY = sensorValueX - x.getMedian();
    float valueZ = sensorValueX - x.getMedian();
    andy.setAlpha(15 * (int)(Math.abs(valueX) + Math.abs(valueY) + Math.abs(valueZ))); 
//..................①
    layout.setBackgroundDrawable(andy);
  }
}

要点如下所示

3个轴的High-pass filter的值,画像的阿尔法值进行操作。按照这样做,手机强烈摇动的时候Android画像被表示。High-pass filter处理对只是对手机倾斜,画面不被表示。只对手机进行摇动的时候画像才表示。

全部源码下载

 

例程下载

例程名称

Android 加速度传感器运用实例 代码下载

大小

35.2 KB

下载

Shake.zip

 

1.5 倾斜传感器
    在加速度传感器的那一节里面Low-Pass Filter的处理和手机的倾斜大致意思我们应该能理解了。但是,到目前为止我们取得的形式不光是这些,作为角度来说,手机的倾斜度能取得到,这样我们处理起来就很方便了。在这种的场合的时候我们就使用倾斜传感器。
1.5.1  倾斜传感器能取到的值
  
在倾斜传感器中我们可以取到方位角(Azimuth),倾斜角(Pitch),回转角(Roll)3个角度的值。下面就对这些值进行说明。
   首先,方位角我们用文字的方式进行表示,北:0度,东
:90度,南:180度,西:270度,如图1-8
  

      图1-8 方位角

     
次之,作为
设备倾斜角水平放置的时候,上下倾斜的角度从-180度开始到180度的范围的值都能取得到。设备若是向上的方向倾斜就减,相反向下方的倾斜就加。
     

    图1-9 倾斜角
     
     最后,
作为回转角设备水平放置的时候,左右倾斜的角度从-90度开始到90度的范围的值都能取得到。设备若是向左的方向倾斜就加,相反右的方向倾斜就减
   

     图1-10 回转角

1.5.2  使用倾斜传感器的例程
      列表1-8代码中描述了倾斜角和回转角的变化的处理。并且,在这个例程中生SurfaceView类中的子类然后进行图片的表示和回转处理。

列表1-8 倾斜角和回转角的变化画面对应回转处理的例程。


package com.mamezou.android.yajirobee;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class YajirobeeView extends SurfaceView implements SurfaceHolder.Callback, SensorEventListener {
  // SurfaceHolder
  private SurfaceHolder holder;
  private Bitmap image;
  private float positionX, positionY;
  // SensorManager 
  private SensorManager sensorManager;

  public YajirobeeView(Context context) {
    super(context);
    image = BitmapFactory.decodeResource(getResources(), R.drawable.balance);
    //create SurfaceHolder
    holder=getHolder();
    holder.addCallback(this);
    holder.setFixedSize(getWidth(),getHeight());
  }

  @Override
  public void surfaceCreated(SurfaceHolder holder) {
    // Get SensorManager        .....①
    sensorManager = (SensorManager)getContext()
        .getSystemService(Context.SENSOR_SERVICE);
    // registerListene
    sensorManager.registerListener(this,
        sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
        SensorManager.SENSOR_DELAY_NORMAL);
    // 
    positionX = (getWidth() - image.getWidth()) * 0.5f;
    positionY = getHeight() * 0.5f - image.getHeight() * 1.5f;
  }

  @Override
  public void surfaceDestroyed(SurfaceHolder holder) {
    sensorManager.unregisterListener(this);
  }

  @Override
  public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
  }

  @Override
  public void onAccuracyChanged(Sensor sensor, int accuracy) {
  }

  @Override
  public void onSensorChanged(SensorEvent e) {
    float azimuth = e.values[SensorManager.DATA_X];
    float pitch = e.values[SensorManager.DATA_Y];
    float roll = e.values[SensorManager.DATA_Z];
    // lockCanvas
    Canvas canvas = holder.lockCanvas();
    // 
    if (canvas != null) {
      canvas.drawColor(Color.WHITE);
      Paint paint = new Paint();
      paint.setStyle(Paint.Style.FILL);
      paint.setColor(0xFF000000);
      canvas.drawText("Azimuth:" + azimuth, 10, 10, paint);
      canvas.drawText("Pitch:" + pitch, 10, 20, paint);
      canvas.drawText("Roll:" + roll, 10, 30, paint);
      float degree = roll;
      if (pitch > 0) {  //............................②
        degree = 180f - degree;
      }
      canvas.rotate(degree, 
              positionX + image.getWidth() * 0.5f, 
              positionY + image.getHeight());   //.....③
      canvas.drawBitmap(image, positionX, positionY, null);
    }
    // unlockCanvasAndPost
    holder.unlockCanvasAndPost(canvas);
  }
}


原创粉丝点击