SensorManager

摘要:
SensorEventListener是一个接口,它定义了方法onSensorChanged()和onAccuracyChanged()[html]viewplaincopySensorEventListenerlistener=newSensorEventListener(){@Overridepublicvoid donAccuracyChange{}@Overridepublic void onSensorChange{}};当传感器的精度发生变化时,将调用onAccuracyChanged()方法,当传感器监测的值发生变化时将调用onSensorChanged()方法。可以看出,SensorEvent参数被传递到onSensorChanged()方法中,该方法包含一个值数组。传感器输出的所有信息都存储在这里。接下来,我们需要调用SensorManager的registerListener()方法来注册SensorEventListener,使其生效。registerListener()方法接收三个参数,第一个是SensorEventListener的实例,第二个是Sensor的实例。我们已经成功地获得了上述两个参数。

光照传感器

Android 中每个传感器的用法其实都比较类似,真的可以说是一通百通了。首先第一步要获取到 SensorManager 的实例

  1. SensorManager senserManager = (SensorManager)  
  2. getSystemService(Context.SENSOR_SERVICE);  


SensorManager 是系统所有传感器的管理器,有了它的实例之后就可以调用getDefaultSensor()方法来得到任意的传感器类型了

  1. Sensor sensor = senserManager.getDefaultSensor(Sensor.TYPE_LIGHT);  


接下来我们需要对传感器输出的信号进行监听,这就要借助 SensorEventListener 来实现了。SensorEventListener 是一个接口,其中定义了 onSensorChanged()和onAccuracyChanged()这两个方法

  1. SensorEventListener listener = new SensorEventListener() {  
  2.   @Override  
  3.     public void onAccuracyChanged(Sensor sensor, int accuracy) {  
  4.    }  
  5.   @Override  
  6.     public void onSensorChanged(SensorEvent event) {  
  7.   }  
  8. };  


当传感器的精度发生变化时就会调用 onAccuracyChanged()方法,当传感器监测到的数值发生变化时就会调用 onSensorChanged()方法。可以看到 onSensorChanged()
方法中传入了一个 SensorEvent 参数,这个参数里又包含了一个 values 数组,所有传感器输出的信息都是存放在这里的。下 面 我 们 还 需 要 调 用 SensorManager 的 registerListener() 方 法 来 注 册SensorEventListener 才能使其生效,registerListener()方法接收三个参数,第一个参数就是 SensorEventListener 的实例,第二个参数是 Sensor 的实例,这两个参数我们在前面都已经成功得到了。第三个参数是用于表示传感器输出信息的更新速率SENSOR_DELAY_UI 、 SENSOR_DELAY_NORMAL 、 SENSOR_DELAY_GAME 和SENSOR_DELAY_FASTEST 这四种值可选,它们的更新速率是依次递增的


  1. senserManager.registerListener(listener, senser, SensorManager.SENSOR_DELAY_NORMAL);  


另外始终要记得, 当程序退出或传感器使用完毕时, 一定要调用 unregisterListener ()方法将使用的资源释放掉

  1. sensorManager.unregisterListener(listener);  


代码:

  1. public class MainActivity extends Activity {  
  2.   
  3.       
  4.       
  5.     SensorManager sensorManager;  
  6.     TextView light;  
  7.     @Override  
  8.     protected void onCreate(Bundle savedInstanceState) {  
  9.         super.onCreate(savedInstanceState);  
  10.         setContentView(R.layout.activity_main);  
  11.           
  12.         light=(TextView) findViewById(R.id.textView1);  
  13.         sensorManager=(SensorManager) getSystemService(Context.SENSOR_SERVICE);  
  14.         Sensor sensor=sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);  
  15.         sensorManager.registerListener(null, sensor, SensorManager.SENSOR_DELAY_NORMAL);  
  16.     }  
  17.   
  18.     @Override  
  19.     protected void onDestroy() {  
  20.         // TODO Auto-generated method stub  
  21.         super.onDestroy();  
  22.         if (sensorManager!=null) {  
  23.             sensorManager.unregisterListener(listener);  
  24.         }  
  25.     }  
  26.     private SensorEventListener listener=new SensorEventListener() {  
  27.           
  28.         @Override  
  29.         public void onSensorChanged(SensorEvent arg0) {  
  30.             // TODO Auto-generated method stub  
  31.             // values数组中第一个下标的值就是当前的光照强度  
  32.             float value=arg0.values[0];  
  33.             light.setText("Current light level is"+value+"lx");  
  34.               
  35.         }  
  36.           
  37.         @Override  
  38.         public void onAccuracyChanged(Sensor arg0, int arg1) {  
  39.             // TODO Auto-generated method stub  
  40.               
  41.         }  
  42.     };  


现在运行一下程序, 你将会在手机上看到当前环境下的光照强度, 根据所处环境的不同,显示的数值有可能是几十到几百勒克斯。而如果你使用强光来照射手机的话,就有可能会达到上千勒克斯的光照强度


SensorManager第1张


加速度传感器:

第一, 获取 Sensor 实例的时候要指定一个加速度传感器的常量, 如下所示:
Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
第二,加速度传感器输出的信息同样也是存放在 SensorEvent 的 values 数组中的,只不过此时的 values 数组中会有三个值,分别代表手机在 X 轴、Y 轴和 Z 轴方向上的加速度信息。X 轴、Y 轴、Z 轴在空间坐标系上的含义需要注意的是,由于地心引力的存在,你的手机无论在世界上任何角落都会有一个重力加速度,这个加速度的值大约是 9.8m/s
2 。当手机平放的时候,这个加速度是作用在 Z 轴上的,当手机竖立起来的时候,这个加速度是作用在 Y 轴上的,当手机横立起来的时候,这个加速度是作用在 X 轴上的


SensorManager第2张



模仿微信摇一摇


  1. package com.example.yaoyiyao;  
  2.   
  3. import android.hardware.Sensor;  
  4. import android.hardware.SensorEvent;  
  5. import android.hardware.SensorEventListener;  
  6. import android.hardware.SensorManager;  
  7. import android.os.Bundle;  
  8. import android.app.Activity;  
  9. import android.content.Context;  
  10. import android.view.Menu;  
  11. import android.widget.Toast;  
  12.   
  13. public class MainActivity extends Activity {  
  14.       
  15.     private SensorManager sensorManager;  
  16.       
  17.   
  18.     @Override  
  19.     protected void onCreate(Bundle savedInstanceState) {  
  20.         super.onCreate(savedInstanceState);  
  21.         setContentView(R.layout.activity_main);  
  22.         sensorManager=(SensorManager) getSystemService(Context.SENSOR_SERVICE);  
  23.         Sensor sensor=sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);  
  24.         sensorManager.registerListener(sensorEventListener, sensor, SensorManager.SENSOR_DELAY_NORMAL);  
  25.           
  26.     }  
  27.   
  28. @Override  
  29. protected void onDestroy() {  
  30.     // TODO Auto-generated method stub  
  31.     super.onDestroy();  
  32.     if (sensorManager!=null) {  
  33.         sensorManager.unregisterListener(sensorEventListener);  
  34.     }  
  35. }  
  36.       
  37. private SensorEventListener sensorEventListener=new SensorEventListener() {  
  38.       
  39.     @Override  
  40.     public void onSensorChanged(SensorEvent arg0) {  
  41.         // TODO Auto-generated method stub  
  42.         // 加速度可能会是负值,所以要取它们的绝对值  
  43.         float xValue=Math.abs(arg0.values[0]);  
  44.         float yValue=Math.abs(arg0.values[1]);  
  45.         float zValue=Math.abs(arg0.values[2]);  
  46.         if (xValue>15||yValue>15||zValue>15) {  
  47.             // 认为用户摇动了手机,触发摇一摇逻辑  
  48.             Toast.makeText(MainActivity.this, "摇一摇",  
  49.             Toast.LENGTH_SHORT).show();  
  50.         }  
  51.     }  
  52.       
  53.     @Override  
  54.     public void onAccuracyChanged(Sensor arg0, int arg1) {  
  55.         // TODO Auto-generated method stub  
  56.           
  57.     }  
  58. };  
  59. }  


方向传感器:

我们需要获取到一个用于表示方向传感器的 Sensor 实例

  1. Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);  


之后在 onSensorChanged()方法中通过 SensorEvent 的 values 数组,就可以得到传感器输出的所有值了。 方向传感器会记录手机在所有方向上的旋转角度



SensorManager第3张


其中,values[0]记录着手机围绕 Z 轴的旋转角度,values[1] 记录着手机围绕 X 轴的旋转角度,values[2] 记录着手机围绕 Y 轴的旋转角度

看起来很美好是吗?但遗憾的是, Android早就废弃了Sensor.TYPE_ORIENTATION这种传感器类型,虽然代码还是有效的,但已经不再推荐这么写了。事实上,Android 获
取手机旋转的方向和角度是通过加速度传感器和地磁传感器共同计算得出的,这也是Android 目前推荐使用的方式。首先我们需要分别获取到加速度传感器和地磁传感器的实例,并给它们注册监听器

  1. Sensor accelerometerSensor = sensorManager.getDefaultSensor(Sensor.  
  2. TYPE_ACCELEROMETER);  
  3. Sensor magneticSensor = sensorManager.getDefaultSensor(Sensor.  
  4. TYPE_MAGNETIC_FIELD);  
  5. sensorManager.registerListener(listener, accelerometerSensor,  
  6. SensorManager.SENSOR_DELAY_GAME);  
  7. sensorManager.registerListener(listener, magneticSensor,  
  8. SensorManager.SENSOR_DELAY_GAME);  


由于方向传感器的精确度要求通常都比较高, 这里我们把传感器输出信息的更新速率提高了一些,使用的是 SENSOR_DELAY_GAME。接下来在 onSensorChanged()方法中可以获取到 SensorEvent 的 values 数组,分别记录着加速度传感器和地磁传感器输出的值。然后将这两个值传入到 SensorManager的 getRotationMatrix()方法中就可以得到一个包含旋转矩阵的 R 数组

  1. SensorManager.getRotationMatrix(R, null, accelerometerValues, magneticValues);  


其中第一个参数 R 是一个长度为 9 的 float 数组,getRotationMatrix()方法计算出的旋转数据就会赋值到这个数组当中。 第二个参数是一个用于将地磁向量转换成重力坐标的旋
转矩阵,通常指定为 null 即可。第三和第四个参数则分别就是加速度传感器和地磁传感器输出的 values 值。得到了 R 数组之后,接着就可以调用 SensorManager 的 getOrientation()方法来计算手机的旋转数据了

  1. SensorManager.getOrientation(R, values)  

alues 是一个长度为 3 的 float 数组,手机在各个方向上的旋转数据都会被存放到这个数组当中。其中 values[0]记录着手机围绕着图 12.3 中 Z 轴的旋转弧度,values[1]记录
着手机围绕 X 轴的旋转弧度,values[2]记录着手机围绕 Y 轴的旋转弧度。注意这里计算出的数据都是以弧度为单位的, 因此如果你想将它们转换成角度还需要调用如下方法:
Math.toDegrees(values[0]);

简易指南针

  1. package com.example.zhinanzhen;  
  2.   
  3. import android.hardware.Sensor;  
  4. import android.hardware.SensorEvent;  
  5. import android.hardware.SensorEventListener;  
  6. import android.hardware.SensorManager;  
  7. import android.os.Bundle;  
  8. import android.app.Activity;  
  9. import android.content.Context;  
  10. import android.util.Log;  
  11. import android.view.Menu;  
  12.   
  13. public class MainActivity extends Activity {  
  14.       
  15.     private SensorManager sensorManager;  
  16.   
  17.     @Override  
  18.     protected void onCreate(Bundle savedInstanceState) {  
  19.         super.onCreate(savedInstanceState);  
  20.         setContentView(R.layout.activity_main);  
  21.           
  22.         sensorManager=(SensorManager) getSystemService(Context.SENSOR_SERVICE);  
  23.         //磁性传感器  
  24.         Sensor magmagneticSensor=sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);  
  25.         //加速度传感器  
  26.         Sensor accelerometerSensor=sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);  
  27.         sensorManager.registerListener(listener, magmagneticSensor, SensorManager.SENSOR_DELAY_GAME);  
  28.           
  29.           
  30.     }  
  31.   
  32.   
  33.     @Override  
  34.     protected void onDestroy() {  
  35.         // TODO Auto-generated method stub  
  36.         super.onDestroy();  
  37.       
  38.     if (sensorManager!=null) {  
  39.         sensorManager.unregisterListener(listener);  
  40.     }  
  41.     }  
  42.       
  43.       
  44.     private SensorEventListener listener=new SensorEventListener() {  
  45.           
  46.         float[] accelerometerValues = new float[3];  
  47.         float[] magneticValues = new float[3];  
  48.           
  49.         @Override  
  50.         public void onSensorChanged(SensorEvent arg0) {  
  51.             // TODO Auto-generated method stub  
  52.             // 判断当前是加速度传感器还是地磁传感器  
  53.             if (arg0.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {  
  54.             // 注意赋值时要调用clone()方法  
  55.             accelerometerValues = arg0.values.clone();  
  56.             } else if (arg0.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {  
  57.             // 注意赋值时要调用clone()方法  
  58.             magneticValues = arg0.values.clone();  
  59.             }  
  60.             float[] R = new float[9];  
  61.             float[] values = new float[3];  
  62.             SensorManager.getRotationMatrix(R, null, accelerometerValues,  
  63.                     magneticValues);  
  64.                     SensorManager.getOrientation(R, values);  
  65.                     Log.d("MainActivity", "value[0] is " + Math.toDegrees(values[0]));  
  66.         }  
  67.           
  68.         @Override  
  69.         public void onAccuracyChanged(Sensor arg0, int arg1) {  
  70.             // TODO Auto-generated method stub  
  71.               
  72.         }  
  73.     };  
  74. }  


如果当前 SensorEvent 中包含的是加速度传感器,就将 values 数组赋值给 accelerometerValues 数组,如果当前 SensorEvent 中包含的是地磁传感器,就将
values 数组赋值给 magneticValues 数组。注意在赋值的时候一定要调用一下 values 数组的 clone()方法, 不然 accelerometerValues 和 magneticValues 将会指向同一个引用。接下来我们分别创建了一个长度为 9 的 R 数组和一个长度为 3 的 values 数组, 然后调用 getRotationMatrix()方法为 R 数组赋值,再调用 getOrientation()方法为 values 数组赋值,这时 values 中就已经包含手机在所有方向上旋转的弧度了。其中 values[0]表示手机围绕 Z 轴旋转的弧度,这里我们调用 Math.toDegrees()方法将它转换成角度,并打印出来。现在运行一下程序,并围绕 Z 轴旋转手机,旋转的角度就会源源不断地在 LogCat 中打印出来了

SensorManager第4张

alues[0]的取值范围是- 180 度到 180 度,其中±180 度表示正南方向,0 度表示正北方向,- 90 度表示正西方向,90 度表示正东方向。虽然目前我们已经得到了这些数值, 但是想要通过它们来判断手机当前的方向显然是一件伤脑筋的事情,因此我们还要想办法将当前的方向直观地显示出来。毫无疑问,最直观的方式当然是通过罗盘和指针来进行显示了,那么下面我们就来继续完善 CompassTest这个项目。这里我事先准备好了两张图片 compass.png 和 arrow.png,分别用于作为指南针的


SensorManager第5张


  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2. android:layout_width="match_parent"  
  3. android:layout_height="match_parent" >  
  4. <ImageView  
  5. android:id="@+id/compass_img"  
  6. android:layout_width="250dp"  
  7. android:layout_height="250dp"  
  8. android:layout_centerInParent="true"  
  9. android:src="@drawable/compass" />  
  10. <ImageView  
  11. android:id="@+id/arrow_img"  
  12. android:layout_width="60dp"  
  13. android:layout_height="110dp"  
  14. android:layout_centerInParent="true"  
  15. android:src="@drawable/arrow" />  
  16. </RelativeLayout>  


  1. public class MainActivity extends Activity {  
  2. private SensorManager sensorManager;  
  3. private ImageView compassImg;  
  4. @Override  
  5. protected void onCreate(Bundle savedInstanceState) {  
  6. super.onCreate(savedInstanceState);  
  7. setContentView(R.layout.activity_main);  
  8. compassImg = (ImageView) findViewById(R.id.compass_img);  
  9. ⋯⋯  
  10. }  
  11. ⋯⋯  
  12. private SensorEventListener listener = new SensorEventListener() {  
  13. float[] accelerometerValues = new float[3];  
  14. float[] magneticValues = new float[3];  
  15. private float lastRotateDegree;  
  16. @Override  
  17. public void onSensorChanged(SensorEvent event) {  
  18. // 判断当前是加速度传感器还是地磁传感器  
  19. if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {  
  20. // 注意赋值时要调用clone()方法  
  21. accelerometerValues = event.values.clone();  
  22. } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {  
  23. // 注意赋值时要调用clone()方法  
  24. magneticValues = event.values.clone();  
  25. }  
  26. float[] values = new float[3];  
  27. float[] R = new float[9];  
  28. SensorManager.getRotationMatrix(R, null, accelerometerValues,  
  29. magneticValues);  
  30. SensorManager.getOrientation(R, values);  
  31. // 将计算出的旋转角度取反,用于旋转指南针背景图  
  32. float rotateDegree = -(float) Math.toDegrees(values[0]);  
  33. if (Math.abs(rotateDegree - lastRotateDegree) > 1) {  
  34. 第 12 章 Android 特色开发,使用传感器  
  35. 473  
  36. RotateAnimation animation = new RotateAnimation (lastRotateDegree,  
  37. rotateDegree, Animation.RELATIVE_TO_SELF, 0.5f, Animation. RELATIVE_TO_SELF, 0.5f);  
  38. animation.setFillAfter(true);  
  39. compassImg.startAnimation(animation);  
  40. lastRotateDegree = rotateDegree;  
  41. }  
  42. }  
  43. ⋯⋯  
  44. };  
  45. }  


这里首先我们在 onCreate()方法中获取到了 ImageView 的实例,它是用于显示指南针的背景图的。然后在 onSensorChanged()方法中使用到了旋转动画技术,我们创建了一
个 RotateAnimation 的实例,并给它的构造方法传入了六个参数,第一个参数表示旋转的起始角度,第二个参数表示旋转的终止角度,后面四个参数用于指定旋转的中心点。这里我们把从传感器中获取到的旋转角度取反,传递给 RotateAnimation,并指定旋转的中心点为指南针背景图的中心,然后调用 ImageView 的 startAnimation ()方法来执行旋转动画。好了,代码就是这么多,现在我们重新运行一下程序,然后随意旋转手机,指南针的背景图也会跟着一起转动



SensorManager第6张

免责声明:文章转载自《SensorManager》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇MaterialRefreshLayout+ListView 下拉刷新 上拉加载(转载)ubuntu 11.10 如何打开terminal(终端)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Android应用的缓冲界面启动界面

Java是这么优美的语言,为什么要是用xml做开发,我不喜欢用xml开发。我现在试试所有的例子都不使用xml开发项目。 第一个例子启动画面。 package com.devdiv.test.ui_test_animation; import android.app.Activity; import android.os.Bundle; import a...

android体系结构介绍

   1)应用程序层          Android平台不仅仅是操作系统,也包含了许多应用程序,诸如SMS短信客户端程序、电话拨号程序、图片浏览器、Web浏览器等应用程序。这些应用程序都是       用Java语言编写的,并且这些应用程序都是可以被开发人员开发的其他应用程序所替换,这点不同于其他手机操作系统固化在系统内部的系统软件,更加灵活和个    ...

android 原生应用、Web应用、混合应用优缺点分析

近期开发几个项目,牵涉到android的几种开发模式。对于原生态开发、web 应用开发以及混合模式开发,本人觉得并非哪一种就是最好的,哪一种就是最差的,这个全然是依据项目的实际需求,选择一种合适的开发模式。他们同一时候具备自己的长处,同一时候也有自身的缺点,我们依据实际情况,取当中的长处,尽量避免掉缺点,才是最好的开发模式。以下,我们就一同看看,这三种开...

Android内核移植

google的android很多人都希望在gphone没有出来之前,把它移植到相关的硬件平台上去。网上看了不少文章,总的感觉是:在这一步走得最远的就是openmoko的一个大师级别的黑客Ben “Benno” Leslie,他曾经试图把目前google发布的android移植到openmoko的平台上去,并且做了10000多行代码的尝试。最终虽然由于ope...

android模拟器访问localhost或127.0.0.1报错

 在一般的Java Web程序开发中,我们通常使用localhost或者127.0.0.1来访问本机的Web服务,但是如果我们在Android模拟器中也采用同样的地址来访问,Android模拟器将无法正常访问到我们的服务,这是为什么呢?我们可以这样来理解:Android的底层是Linux kernel,包括Android本身就是一个操作系统,因此,这时我们...

[转]Android 操作SQLite基本用法

在Android开发中SQLite起着很重要的作用,网上SQLite的教程有很多很多,不过那些教程大多数都讲得不是很全面。本人总结了一些SQLite的常用的方法,借着论坛的大赛,跟大家分享分享的。一.SQLite的介绍1.SQLite简介SQLite是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入  式的,而且目前已经在很多嵌入...