Android传感器的使用总结
一.Android传感器的基础概念
随着手机的发展,现在各大手机支持的传感器类型也越来越多,在开发中利用传感器进行某些操作令人们有一种耳目一新的感觉,例如微信中的摇一摇,以及手机音乐播放器中的摇一摇切歌。今天来简单介绍下Android中传感器的使用以及一些常用的传感器。
(一)传感器种类
1.动作传感器
Android平台支持一些用于监视设备动作的传感器(这样的传感器共有5个)。其中两个 (加速传感器( TYPE_ACCELEROMETER)和陀螺仪(TYPE_GYROSCOPE)传感器)是纯的硬件传感器。 另外三个(重力传感器、线性加速传感器和旋转向量传感器)可能是硬件传感器,也可能 是软件传感器。例如,在一些Android设备中,这些基于软件的传感器会从加速和磁力传感器中获取数 据,但在另一些Android设备中也可能从陀螺仪传感器中获取数据。也就是说,同一种基于软件的传感器在不同的Android设备中回传的数据可能来自不同的硬件传感器。所以基于软件的同一种传感器在不同的设备中可能精确度、使用范围有所不同。大多数高端 Android设备都会有加速传感器,还有一些拥有陀螺仪传感器。
2.位置传感器
Android平台提供了两个传感器用于确定设备的位置,这两个传感器是磁场传感器和方向传感器。Android平台还提供了测量设备正面到某一个邻近物体距离的传感器(邻近传感 器)。磁场传感器和邻近传感器是基于硬件的传感器。大多数Android手机和平板电脑都 有磁场传感器。而邻近传感器通常在手机中很常见。因为可以用该传感器测试接听电话时 手机屏幕离脸有多远。可以可以在贴近耳朵接听电话时完成某些工作。方向传感器是基于 软件的,该传感器的回传数据来自加速度传感器和磁场传感器。
3.环境传感器
Android平台提供了4个传感器,用于检测不同的外部环境。我们可以使用这些传感器检测 周围。例如,可以检测周围空气的湿度、光线、空气的压强和温度。这4个传感器都是基于 硬件的传感器。除了光线传感器外,其他3个传感器在普通的Android设备中很少见。所以 如果使用环境传感器,最好运行时对当前Android设备所支持的传感器是否检测。
(二)Android传感器一览表
传感器类型名称 传感器类别 系统定义的传感器常量 传感器常量对应的数值
1. 加速度 TYPE_ACCELEROMETER SENSOR_TYPE_ACCELEROMETER 1
2. 磁力域 TYPE_MAGNETIC_FIELD SENSOR_TYPE_MAGNETIC_FIELD 2
3. 方向 TYPE_ORIENTATION SENSOR_TYPE_ORIENTATION 3
4. 陀螺 TYPE_GYROSCOPE SENSOR_TYPE_GYROSCOPE 4
5. 光线(亮度)TYPE_LIGHT SENSOR_TYPE_LIGHT 5
6. 压力 TYPE_PRESSURE SENSOR_TYPE_PRESSURE 6
7. 温度 TYPE_TEMPERATURE SENSOR_TYPE_TEMPERATURE 7
8. 临近性 TYPE_PROXIMITY SENSOR_TYPE_PROXIMITY 8
(三)SensorManager管理器
1.SensorManager获取所有传感器
Android所有的传感器都归传感器管理器 SensorManager 管理,获取传感器管理器的方法很简单:
SensorManager sensorManager = (SensorManager)getSystemService(Context.S ENSOR_SERVICE);
(四)从传感器管理器中获取其中某个或者某些传感器的方法有如下三种:
第一种:获取某种传感器的默认传感器 Sensor defaultGyroscope = sensorManager.getDefaultSensor(Sensor. TYPE_GYROSCOPE);第二种:获取某种传感器的列表 List pressureSensors = sensorManager.getSensorList(Sensor.TYPE_PRESSURE); 第三种:获取所有传感器的列表List allSensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
(五)对于某一个传感器,它的一些具体信息的获取方法可以见下表:
1. getMaximumRange() 最大取值范围
2. getName() 设备名称
3. getPower() 功率
4. getResolution() 精度
5. getType() 传感器类型
6. getVentor() 设备供应商
7. getVersion() 设备版本号
(六)注册SensorListener
注册传感器监听状态的改变,能在状态改变的回调方法中,操作相应的行为。
注册SensorListener的方法,三个参数
sensorManager.regesterListener(SensorEventListener listener, Sensor sensor, int rate);
第一个参数为传感器监听
第二个参数为当前注册的传感器
第三个参数是延迟时间的精密度,
精密度可选择的值
1.SensorManager.SENSOR_DELAY_FASTEST 0ms
2.SensorManager.SENSOR_DELAY_GAME 20ms
3.SensorManager.SENSOR_DELAY_UI 60ms
4.SensorManager.SENSOR_DELAY_NORMAL 200ms
(七)取消注册SensorManager
一般在onDestroy方法里面取消。
sensorManager. unregisterListener(SensorEventListener listener);
(八)SensorEventListener监听
要监视原始的传感器数据,你需要实现两个通过SensorEventListener接口暴露的回调方法:onAccuracyChanged()和onSensorChanged()。
Android系统在任何发生下列事情的时 候都会调用这两个方法:
1.onAccuracyChanged传感器精度的改变:
这种情况中,系统会调用onAccuracyChanged()方法,它提供了你要引用的发生精度变化的 Sensor对象。精度使用以下四个状态常量之一来代表的:
(1) SENSOR_STATUS_ACCURACY_LOW
(2) SENSOR_STATUS_ACCURACY_MEDIUM
(3)SENSOR_STATUS_ACCURACY_HIGH
(4) SENSOR_STATUS_UNRELIABLE
2.onSensorChanged传感器报告新的值:
这个也是我们一般情况下去重写的回调方法。
这种情况中,系统会调用onSensorChanged()方法,它提供了一个SensorEvent对象。 SensorEvent对象包含了有关新的传感器数据的信息,包括:数据的精度、产生数据的传感器、产生数据时的时间戳、以及传感器记录的新的数据。
注意:传感器是非常耗电的,在不用时一定要释放。
二.几种重要的传感器详细介绍
(一)动作传感器的作用
动作传感器对于监测设备的移动非常有用,例如,倾斜、震动、旋转和摆动都属于动作传感器的监 测范围。设备的移动通常是对用户输入的直接反应。例如,用户正在游戏中飙车,或控制游戏中的一个小球)。除此之外,设备所处的物理环境也会反应在设备的动作上,例如,用户正常驾驶汽车,而这是 Android设备正安静地躺在旁边的座椅上,尽管设备没有移动,但会随着车的行驶而不断震动,而且 设备也会随着汽车的移动而移动。 对于第一种情况,可以对设备本身的相对位置进行监测。而对于第二种情况,需要考虑到设备以外的参 照系。动作传感器本身一般并不会用于监测设备的位置,关于设备的位置需要用其他类型的传感器进行 监测,例如,磁场传感器。
(二)动作传感器的回传数据
所有的动作传感器都会返回三个浮点数的值(通过长度为3的数组返回),但对于不同的传感器,这三个只的意义不同。例如,对于加速传感器,会返回三个坐标轴的数据[。对于陀螺仪传感器,会返回三个坐标轴的旋转角速度。
应用:动作传感器_摇一摇
(三)方向传感器
方向传感器有三个方向的属性值。
1.SensorEvent.values[0]: 绕着Z轴旋转的角度。
如果Y轴(正常拿手机的方向)正对着北方,该值是0,如果Y轴指向南 方,改值是180,Y轴指向东方,该值是90,如果Y轴指向西方,该值是270。
2.SensorEvent.values[1]: 绕着X轴旋转的度数。
当从Z轴正方向朝向Y轴正方向,改值为正值。反之,为负值。该值在 180至-180之间变动。
3.ensorEvent.values[2]:绕着Y轴旋转的度数。
从Z轴正方向朝向X轴正方向,改值为正值。反之,为负值。该值在180至-180之间变动。 应用:方向传感器_指南针
(四)磁场传感器
这个传感器一般开发不会用到!
SensorEvent.values[0]: 沿着X轴的磁力(μT,millitesla) SensorEvent.values[1]: 沿着Y轴的磁力(μT,millitesla) SensorEvent.values[2]: 沿着Z轴的磁力(μT,millitesla)
(五)邻近传感器
这里只返回一个参数
SensorEvent.values[0]:
手机正面距离邻近物理的距离(CM)
应用:手机接电话时屏幕熄屏
(六)光线传感器的一些值的标准
- 最强的光线强度(估计只有沙漠地带才能达到这个值)
public static final float LIGHT_SUNLIGHT_MAX = 120000.0f;
2.万里无云时阳光直射的强度
public static final float LIGHT_SUNLIGHT = 110000.0f; - 有阳光,但被云彩抵消了部分光线时的强度
public static final float LIGHT_SHADE = 20000.0f; 4.多云时的光线强度
public static final float LIGHT_OVERCAST = 10000.0f;
5.太阳刚刚升起时(日出)的光线强度
public static final float LIGHT_SUNRISE = 400.0f;
6.在阴雨天,没有太阳时的光线强度
public static final float LIGHT_CLOUDY = 100.0f;
7.夜晚有月亮时的光线强度
public static final float LIGHT_FULLMOON = 0.25f;
8.夜晚没有月亮时的光线强度(当然,也不能有路灯,就是漆黑一片)
public static final float LIGHT_NO_MOON = 0.001f;
一般的传感器的使用时不用权限的,比如摇一摇,控制屏幕中图像的上下左右滚动等等。
三.传感器使用的一个简单示例
本示例只要是显示手机中存在的传感器的类型在List View中罗列出来。
(一)布局文件activity_main.xml的设计
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <HorizontalScrollView android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:padding="20dp" android:id="@+id/main_tv" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="text" /> HorizontalScrollView> <ListView android:id="@+id/main_lv" android:layout_width="match_parent" android:layout_height="match_parent" />LinearLayout>
布局中使用一个ScrollView来显示某一个具体的传感器的所有的数据,使用一个ListVIew显示所有的传感器的类型。
(二)java代码的设计
package com.lwz.sensor;import android.hardware.Sensor;import android.hardware.SensorEvent;import android.hardware.SensorEventListener;import android.hardware.SensorManager;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ListView;import android.widget.TextView;import java.util.List;/** * 传感器的使用 */public class MainActivity extends AppCompatActivity { //定义传感器的管理器 SensorManager sensorManager; //定义布局内的控件 ListView listView; TextView tv; //获取所有的管理器 List sensors; //获取某一种传感器 Sensor sensor; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); sensorManager = (SensorManager) getSystemService(this.SENSOR_SERVICE); //实例化传感器的管理器 listView = (ListView) findViewById(R.id.main_lv);//实例化布局 tv = (TextView) findViewById(R.id.main_tv); initTv(); //获取所有的管理器 sensors = sensorManager.getSensorList(Sensor.TYPE_ALL); listView.setAdapter(adapter); } /** * 给TextView设置一个文本,某一个类型的传感器的具体数据 * 这里显示的是加速传感器的数据 */ private void initTv() { sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); if (sensor != null) { String name = sensor.getName();//名称 float range = sensor.getMaximumRange();//最大取值范围 float power = sensor.getPower();// 功率 float resol = sensor.getResolution();// 精度 int type = sensor.getType(); //传感器类型 String vendor = sensor.getVendor(); //设备供应商 int version = sensor.getVersion(); //设备版本号 tv.setText("名称" + name + ",最大取值范围" + range + ",功率" + power + ",精度" + resol + ",传感器类型" + type + ",供应商" + vendor + ",版本号" + version); } else { tv.setText("没有该传感器的数据显示"); } } private BaseAdapter adapter = new BaseAdapter() { @Override public int getCount() { return sensors.size(); } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = View.inflate(getBaseContext(), android.R.layout.simple_list_item_1, null); } TextView tv = (TextView) convertView; Sensor sensor = sensors.get(position); tv.setText(position + ":" + sensor.getName() + " "); switch (sensor.getType()) { case Sensor.TYPE_ACCELEROMETER: tv.append(" 加速度传感器"); break; case Sensor.TYPE_LIGHT: tv.append(" 光线"); break; case Sensor.TYPE_GRAVITY: tv.append(" 重力"); break; default: tv.append(" 其他"); break; } return convertView; } }; /*** * 在onStart中注册传感器的监听事件 */ @Override protected void onStart() { super.onStart(); //精准度 sensorManager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_FASTEST); } /** * 传感器的监听对象 */ SensorEventListener listener = new SensorEventListener() { //传感器改变时,一般是通过这个方法里面的参数确定传感器状态的改变 @Override public void onSensorChanged(SensorEvent event) { // Log.e("TAG", "-------传感状态发生变化-------"); //获取传感器的数据 float[] values = event.values; float max = sensor.getMaximumRange();//获取最大值范围 if (values.length >= 3) { float x = values[0]; float y = values[1]; float z = values[2]; if (x > max / 5) { Log.e("TAG", "--------------" + max + " " + x + " " + y + " " + z); } } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { //当精准度改变时 } }; /*** * 在onDestroy中注销传感器的监听事件 */ @Override protected void onDestroy() { super.onDestroy(); sensorManager.unregisterListener(listener); }}
(三)程序运行后的界面:
注意这里每一个手机显示的传感器的个数一般不相同,模拟器显示很少种类,一般手机都能显示4、5个,好一点的手机会显示9个或更多。
手机模拟器的显示情况:
真机显示情况:
另外在AndroidStudio中也会显示很多的Log信息,这里先不展示。
四.设计一个跟随屏幕翻动而滚动的小球的示例
这里利用的是方向传感器,但是只取其中的两个方向就可以实现了。
(一)创建一个自定义View来显示小球和简单背景
package com.lwz.sensor;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Point;import android.util.AttributeSet;import android.view.View;/** * 自定义的小球 */public class MyView extends View { public MyView(Context context) { super(context); initView(); } public MyView(Context context, AttributeSet attrs) { super(context, attrs); initView(); } //创建画笔 Paint paint = new Paint(); //设置一个圆心的点 Point point = new Point(); int width; int height; int currentX; int currentY; //初始化数据 void initView() { //对画笔的基本设置 //设置抗锯齿 paint.setAntiAlias(true); //设置防抖动 paint.setDither(true); //设置颜色 paint.setColor(Color.RED); //设置透明的 paint.setAlpha(128); //设置线条粗细 paint.setStrokeWidth(10); width = getResources().getDisplayMetrics().widthPixels; height = getResources().getDisplayMetrics().heightPixels; currentX = width / 2; currentY = height / 2; point.set(width / 2, height / 2); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //绘制多条直线 canvas.drawLines(new float[]{0, height / 2, width , height / 2, width / 2, 0, width / 2, height,}, paint); paint.setStyle(Paint.Style.FILL);// //绘制一个实心圆(默认情况) canvas.drawCircle(currentX, currentY, 50, paint); //画一个空心圆也设置画笔 paint.setStyle(Paint.Style.STROKE);// canvas.drawCircle(width / 2, height / 2, width / 2, paint); }//当屏幕方向发生改变时,调用这个方法对小球进行重绘 public void initdata(int x, int y) { currentX = currentX-x; currentY = currentY-y; invalidate();//重绘 }}
(二)布局文件的设计
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <com.lwz.sensor.MyView android:layout_centerInParent="true" android:id="@+id/second_myView" android:layout_width="wrap_content" android:layout_height="wrap_content" />RelativeLayout>
(三)主方法的java代码
package com.lwz.sensor;import android.app.Activity;import android.hardware.Sensor;import android.hardware.SensorEvent;import android.hardware.SensorEventListener;import android.hardware.SensorManager;import android.os.Bundle;/** * 跟随的小球的设置 */public class SecondActivity extends Activity { //定义传感器的管理器 SensorManager sensorManager; //定义布局内的控件 MyView myView; //获取某一种传感器 Sensor sensor; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_bor); myView= (MyView) findViewById(R.id.second_myView); sensorManager = (SensorManager) getSystemService(this.SENSOR_SERVICE); //实例化传感器的管理器 sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); } /*** * 在onStart中注册传感器的监听事件 */ @Override protected void onStart() { super.onStart(); //注册监听传感状态 sensorManager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_FASTEST); } /** * 传感器的监听对象 */ SensorEventListener listener = new SensorEventListener() { //传感器改变时,一般是通过这个方法里面的参数确定传感器状态的改变 @Override public void onSensorChanged(SensorEvent event) { // Log.e("TAG", "-------传感状态发生变化-------"); //获取传感器的数据 float[] values = event.values; float max = sensor.getMaximumRange();//获取最大值范围 if (values.length >= 3) { float x = values[0]; float y = values[1]; float z = values[2]; if (Math.abs(x) > max / 8) { myView.initdata((int)x,(int)y); } if (Math.abs(y) > max /8) { myView.initdata((int)x,-(int)y); } } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { //当精准度改变时 } }; /*** * 在onDestroy中注销传感器的监听事件 */ @Override protected void onDestroy() { super.onDestroy(); sensorManager.unregisterListener(listener); }}
传感器的测试要在真机中运行。
程序运后显示的界面:
当手机往右边和下边倾斜后显示的效果:
但手机向某一个方向倾斜,小球就会想某个方向去滑动,这里小球没有设置边界,所以小球会滑出屏幕外面,想要设置其实也是很简单的,在MyView里面设置就可以了。
关于Android传感器的使用并不是很多,一般的学会使用加速度传感器和方向传感器就可以了。而且使用它们都是不用添加权限的。
更多相关文章
- 关于如何惟一地标识一台Android设备的综合性讨论
- android中传感器的应用
- 关于蓝牙设备之间共享网络的问题(android4.2)
- Android设备检测
- Android判断设备是手机还是平板
- Android设备的显示信息
- Android中获取设备的IP