前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android开发笔记(五十九)巧用传感器

Android开发笔记(五十九)巧用传感器

作者头像
aqi00
发布2019-01-18 11:09:05
1.2K0
发布2019-01-18 11:09:05
举报
文章被收录于专栏:老欧说安卓老欧说安卓

传感器Sensor

传感器是Android用来感知周围环境以及运动信息的工具。因为具体的感应信息依赖于相关硬件,所以虽然Android提供了众多的感应器,但不是每部手机都能支持这么多感应器,恰恰相反,大多数安卓手机仅仅支持包括加速度在内的少数几个感应器。 传感器借助于硬件来监听环境改变的事件,从这个意义上来说,Android的事件都是由某个传感器触发,只不过这个触发来源可能是软件,也可能是屏幕,甚至可能是手机的sim卡。回顾一下之前的事件通信章节,我们会发现,原来它们在本质上跟传感器是类似的,比如说: 1、软件感应:UI事件(参见《Android开发笔记(四十四)动态UI事件》)、媒体播放事件(参见《Android开发笔记(五十七)录像录音与播放》)、浏览器加载、交互与下载事件(参见《Android开发笔记(六十四)网页加载与JS调用》)。 2、屏幕感应:点击事件(参见《Android开发笔记(四十三)点击事件》)、手势事件(参见《Android开发笔记(四十五)手势事件》)、拖动条的拖动事件(参见《Android开发笔记(五十八)铃声与震动》)。 3、sim卡感应:手机相关事件(参见《Android开发笔记(四十六)手机相关事件》)。 4、摄像头感应:拍照事件(参见《Android开发笔记(五十六)摄像头拍照》)。 5、麦克风感应:录音事件(参见《Android开发笔记(五十七)录像录音与播放》)。 6、系统感应:电量事件、屏幕开关事件(参见《Android开发笔记(一百一十七)app省电方略》)。 下面是目前Android支持的感应器类型: 1 TYPE_ACCELEROMETER //加速度 2 TYPE_MAGNETIC_FIELD //磁场 3 TYPE_ORIENTATION //方向,该类型已弃用,取而代之的是getOrientation方法 4 TYPE_GYROSCOPE //陀螺仪 5 TYPE_LIGHT //光线 6 TYPE_PRESSURE //压力 7 TYPE_TEMPERATURE //温度,该类型已弃用,取而代之的是TYPE_AMBIENT_TEMPERATURE 8 TYPE_PROXIMITY //距离 9 TYPE_GRAVITY //重力 10 TYPE_LINEAR_ACCELERATION //线性加速度 11 TYPE_ROTATION_VECTOR //旋转矢量 12 TYPE_RELATIVE_HUMIDITY //湿度 13 TYPE_AMBIENT_TEMPERATURE //环境温度 14 TYPE_MAGNETIC_FIELD_UNCALIBRATED //无标定磁场 15 TYPE_GAME_ROTATION_VECTOR //无标定旋转矢量 16 TYPE_GYROSCOPE_UNCALIBRATED //未校准陀螺仪 17 TYPE_SIGNIFICANT_MOTION //特殊动作 18 TYPE_STEP_DETECTOR //步行检测,用户每走一步就触发一次事件 19 TYPE_STEP_COUNTER //计步器,记录激活后的步伐数 20 TYPE_GEOMAGNETIC_ROTATION_VECTOR //地磁旋转矢量

加速度感应器/摇一摇

这个功能最有名的应用就是微信里的“摇一摇”了,用户通过摇晃手机来寻找周围的人;类似的业务还有摇奖、玩游戏等等。

下面以摇一摇的实现来演示传感器开发的步骤:

1、声明一个SensorManager对象,该对象从系统服务Context.SENSOR_SERVICE中获取实例; 2、编写一个传感器事件监听器,该监听器继承自SensorEventListener,同时需实现onSensorChanged和onAccuracyChanged两个方法。其中前一个方法在感应变化时触发,业务逻辑都在这边处理;后一个方法在精度改变时触发,一般无需处理。 3、重写onResume方法,在该方法中注册传感器监听事件,使用的是registerListener方法,该方法的第二个参数为Sensor类型,须调用SensorManager对象的getDefaultSensor来获取指定类型的传感器对象。例如摇一摇功能要注册加速度感应监听器,代码示例如下:

代码语言:javascript
复制
		mSensroMgr.registerListener(this,
				mSensroMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
				SensorManager.SENSOR_DELAY_NORMAL);

4、重写onPause方法,在该方法中注销传感器事件,代码示例如下:

代码语言:javascript
复制
		mSensroMgr.unregisterListener(this);

下面是摇一摇功能的核心代码:

代码语言:javascript
复制
			float[] values = event.values;
			if (sensorType == Sensor.TYPE_ACCELEROMETER) {
				if ((Math.abs(values[0]) > 15 || Math.abs(values[1]) > 15 
						|| Math.abs(values[2]) > 15)) {
					tv_shake.setText(getNowDateTime()+" 恭喜您摇一摇啦");
					//系统检测到摇一摇事件后,震动手机提示用户
					mVibrator.vibrate(500);
				}
			}

前置摄像头的感应

博主的手机比较廉价,支持的感应器不多,除了加速度之外,就只有光线与距离感应器了。不过很奇怪,距离感应器只能探测到0-1厘米的距离,不会探测到2厘米以上的距离。于是好好琢磨了下,发现只有遮挡手机上面扬声器与前置摄像头所在的位置,距离感应才会变化,遮挡屏幕其余地方,距离感应并无变化。同样的,光线感应也是如此,把手机上部遮住,光线强度一下就降得很低。据此,我推测,光线与距离很可能是依靠前置摄像头来感应,所以一旦遮住前置摄像头,光线与距离感应马上就被触发了。

代码示例

下面是摇一摇、光线与距离感应的效果截图:

下面是传感器开发(摇一摇)的完整代码例子:

代码语言:javascript
复制
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
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.os.Vibrator;
import android.util.Log;
import android.widget.TextView;

import com.example.exmcamera.R;

public class SensorActivity extends Activity implements SensorEventListener {

	private static final String TAG = "SensorActivity";
	private TextView tv_sensor;
	private TextView tv_shake;
	private TextView tv_light;
	private TextView tv_distance;
	private SensorManager mSensroMgr;
	private Vibrator mVibrator;
	private String[] mSensorType = {
			"加速度", "磁场", "方向", "陀螺仪", "光线", 
			"压力", "温度", "距离", "重力", "线性加速度", 
			"旋转矢量", "湿度", "环境温度", "无标定磁场", "无标定旋转矢量", 
			"未校准陀螺仪", "特殊动作", "步行检测", "计步器", "地磁旋转矢量"};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_sensor);

		tv_sensor = (TextView) findViewById(R.id.tv_sensor);
		tv_shake = (TextView) findViewById(R.id.tv_shake);
		tv_light = (TextView) findViewById(R.id.tv_light);
		tv_distance = (TextView) findViewById(R.id.tv_distance);
		mSensroMgr = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
		mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
		showSensorInfo();
	}

	private void showSensorInfo() {
		List<Sensor> sensorList = mSensroMgr.getSensorList(Sensor.TYPE_ALL);
		ArrayList<String> sensorNameList = new ArrayList<String>();
		String show_content = "当前支持的传感器包括:\n";
		for (Sensor sensor : sensorList) {
			sensorNameList.add(sensor.getName());
			String content = String.format("%s:%s\n", 
					mSensorType[sensor.getType()-1], sensor.getName());
			show_content += content;
		}
		tv_sensor.setText(show_content);
	}

	private String getNowDateTime() {
		SimpleDateFormat s_format = new SimpleDateFormat("HH:mm:ss");
		Date d_date = new Date();
		String s_date = "";
		s_date = s_format.format(d_date);
		return s_date;
	}

	@Override
	protected void onPause() {
		super.onPause();
		mSensroMgr.unregisterListener(this);
	}

	@Override
	protected void onResume() {
		super.onResume();
		mSensroMgr.registerListener(this,
				mSensroMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
				SensorManager.SENSOR_DELAY_NORMAL);
		mSensroMgr.registerListener(this,
				mSensroMgr.getDefaultSensor(Sensor.TYPE_LIGHT),
				SensorManager.SENSOR_DELAY_NORMAL);
		mSensroMgr.registerListener(this,
				mSensroMgr.getDefaultSensor(Sensor.TYPE_PROXIMITY),
				SensorManager.SENSOR_DELAY_NORMAL);
	}
  
	@Override
	public void onSensorChanged(SensorEvent event) {
		int sensorType = event.sensor.getType();
		if (sensorType == Sensor.TYPE_ACCELEROMETER) {
			// values[0]:X轴,values[1]:Y轴,values[2]:Z轴
			float[] values = event.values;
			if (sensorType == Sensor.TYPE_ACCELEROMETER) {
				if ((Math.abs(values[0]) > 15 || Math.abs(values[1]) > 15 
						|| Math.abs(values[2]) > 15)) {
					tv_shake.setText(getNowDateTime()+" 恭喜您摇一摇啦");
					//系统检测到摇一摇事件后,震动手机提示用户
					mVibrator.vibrate(500);
				}
			}
		} else if (sensorType == Sensor.TYPE_LIGHT) {
			float light_strength = event.values[0];
			tv_light.setText(getNowDateTime()+" 当前光线强度为"+light_strength);
		} else if (sensorType == Sensor.TYPE_PROXIMITY) {
			float distance = event.values[0];
			tv_distance.setText(getNowDateTime()+" 有不明物体接近!距离"+distance+"厘米");
		}
	}

	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
		//当传感器精度改变时回调该方法,一般无需处理
	}
	
}

点击下载本文用到的传感器操作的工程代码 点此查看Android开发笔记的完整目录

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年02月06日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 传感器Sensor
  • 加速度感应器/摇一摇
  • 前置摄像头的感应
  • 代码示例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档