光照传感器

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

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

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

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

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

SensorEventListener listener = new SensorEventListener() {@Overridepublic void onAccuracyChanged(Sensor sensor, int accuracy) {}@Overridepublic void onSensorChanged(SensorEvent event) {}
};

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

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

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

sensorManager.unregisterListener(listener);

代码:

public class MainActivity extends Activity {SensorManager sensorManager;TextView light;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);light=(TextView) findViewById(R.id.textView1);sensorManager=(SensorManager) getSystemService(Context.SENSOR_SERVICE);Sensor sensor=sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);sensorManager.registerListener(null, sensor, SensorManager.SENSOR_DELAY_NORMAL);}@Overrideprotected void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();if (sensorManager!=null) {sensorManager.unregisterListener(listener);}}private SensorEventListener listener=new SensorEventListener() {@Overridepublic void onSensorChanged(SensorEvent arg0) {// TODO Auto-generated method stub// values数组中第一个下标的值就是当前的光照强度float value=arg0.values[0];light.setText("Current light level is"+value+"lx");}@Overridepublic void onAccuracyChanged(Sensor arg0, int arg1) {// TODO Auto-generated method stub}};

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

加速度传感器:

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

模仿微信摇一摇

package com.example.yaoyiyao;import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.view.Menu;
import android.widget.Toast;public class MainActivity extends Activity {private SensorManager sensorManager;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);sensorManager=(SensorManager) getSystemService(Context.SENSOR_SERVICE);Sensor sensor=sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);sensorManager.registerListener(sensorEventListener, sensor, SensorManager.SENSOR_DELAY_NORMAL);}@Override
protected void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();if (sensorManager!=null) {sensorManager.unregisterListener(sensorEventListener);}
}private SensorEventListener sensorEventListener=new SensorEventListener() {@Overridepublic void onSensorChanged(SensorEvent arg0) {// TODO Auto-generated method stub// 加速度可能会是负值,所以要取它们的绝对值float xValue=Math.abs(arg0.values[0]);float yValue=Math.abs(arg0.values[1]);float zValue=Math.abs(arg0.values[2]);if (xValue>15||yValue>15||zValue>15) {// 认为用户摇动了手机,触发摇一摇逻辑Toast.makeText(MainActivity.this, "摇一摇",Toast.LENGTH_SHORT).show();}}@Overridepublic void onAccuracyChanged(Sensor arg0, int arg1) {// TODO Auto-generated method stub}
};
}

方向传感器:

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

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

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

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

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

Sensor accelerometerSensor = sensorManager.getDefaultSensor(Sensor.
TYPE_ACCELEROMETER);
Sensor magneticSensor = sensorManager.getDefaultSensor(Sensor.
TYPE_MAGNETIC_FIELD);
sensorManager.registerListener(listener, accelerometerSensor,
SensorManager.SENSOR_DELAY_GAME);
sensorManager.registerListener(listener, magneticSensor,
SensorManager.SENSOR_DELAY_GAME);

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

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

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

SensorManager.getOrientation(R, values)

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

简易指南针

package com.example.zhinanzhen;import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.Menu;public class MainActivity extends Activity {private SensorManager sensorManager;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);sensorManager=(SensorManager) getSystemService(Context.SENSOR_SERVICE);//磁性传感器Sensor magmagneticSensor=sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);//加速度传感器Sensor accelerometerSensor=sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);sensorManager.registerListener(listener, magmagneticSensor, SensorManager.SENSOR_DELAY_GAME);}@Overrideprotected void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();if (sensorManager!=null) {sensorManager.unregisterListener(listener);}}private SensorEventListener listener=new SensorEventListener() {float[] accelerometerValues = new float[3];float[] magneticValues = new float[3];@Overridepublic void onSensorChanged(SensorEvent arg0) {// TODO Auto-generated method stub// 判断当前是加速度传感器还是地磁传感器if (arg0.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {// 注意赋值时要调用clone()方法accelerometerValues = arg0.values.clone();} else if (arg0.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {// 注意赋值时要调用clone()方法magneticValues = arg0.values.clone();}float[] R = new float[9];float[] values = new float[3];SensorManager.getRotationMatrix(R, null, accelerometerValues,magneticValues);SensorManager.getOrientation(R, values);Log.d("MainActivity", "value[0] is " + Math.toDegrees(values[0]));}@Overridepublic void onAccuracyChanged(Sensor arg0, int arg1) {// TODO Auto-generated method stub}};
}

如果当前 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 中打印出来了

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

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="@+id/compass_img"
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_centerInParent="true"
android:src="@drawable/compass" />
<ImageView
android:id="@+id/arrow_img"
android:layout_width="60dp"
android:layout_height="110dp"
android:layout_centerInParent="true"
android:src="@drawable/arrow" />
</RelativeLayout>
public class MainActivity extends Activity {
private SensorManager sensorManager;
private ImageView compassImg;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
compassImg = (ImageView) findViewById(R.id.compass_img);
⋯⋯
}
⋯⋯
private SensorEventListener listener = new SensorEventListener() {
float[] accelerometerValues = new float[3];
float[] magneticValues = new float[3];
private float lastRotateDegree;
@Override
public void onSensorChanged(SensorEvent event) {
// 判断当前是加速度传感器还是地磁传感器
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
// 注意赋值时要调用clone()方法
accelerometerValues = event.values.clone();
} else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
// 注意赋值时要调用clone()方法
magneticValues = event.values.clone();
}
float[] values = new float[3];
float[] R = new float[9];
SensorManager.getRotationMatrix(R, null, accelerometerValues,
magneticValues);
SensorManager.getOrientation(R, values);
// 将计算出的旋转角度取反,用于旋转指南针背景图
float rotateDegree = -(float) Math.toDegrees(values[0]);
if (Math.abs(rotateDegree - lastRotateDegree) > 1) {
第 12 章 Android 特色开发,使用传感器
473
RotateAnimation animation = new RotateAnimation (lastRotateDegree,
rotateDegree, Animation.RELATIVE_TO_SELF, 0.5f, Animation. RELATIVE_TO_SELF, 0.5f);
animation.setFillAfter(true);
compassImg.startAnimation(animation);
lastRotateDegree = rotateDegree;
}
}
⋯⋯
};
}

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

传感器SensorManager相关推荐

  1. android动作传感器

    android动作传感器 Android平台支持一些用于监视设备动作的传感器(这样的传感器共有5个).其中两个(加速传感器和陀螺仪传感器)是纯的硬件传感器.另外三个(重力传感器.线性加速传感器和旋转向 ...

  2. android 获取加速度传感器值,Android开发获取传感器数据的方法示例【加速度传感器,磁场传感器,光线传感器,方向传感器】...

    本文实例讲述了Android开发获取传感器数据的方法.分享给大家供大家参考,具体如下: package mobile.android.sensor; import java.util.List; im ...

  3. Android 传感器分类

    public static final int  TYPE_ACCELEROMETER = 1 加速度传感器 public static final int TYPE_MAGNETIC_FIELD = ...

  4. Android 硬件传感器

    为什么80%的码农都做不了架构师?>>> 1. 传感器入门 自从苹果公司在2007年发布第一代iPhone以来,以前看似和手机挨不着边的传感器也逐渐成为手机硬件的重要组成部分.如果读 ...

  5. android开发中磁场传感器,Android传感器(加速度传感器,磁场传感器,光线传感器,方向传感器)...

    [android]代码库package mobile.android.sensor; import java.util.List; import android.app.Activity; impor ...

  6. android开发中磁场传感器,Android开发获取传感器数据的方法示例【加速度传感器,磁场传感器,光线传感器,方向传感器】...

    本文实例讲述了Android开发获取传感器数据的方法.分享给大家供大家参考,具体如下: package mobile.android.sensor; import java.util.List; im ...

  7. android学习笔记之磁场传感器制做指南针

    布局添加一个imageView,在加一个自定义pointer视图(需要加上包名) <FrameLayoutxmlns:android="http://schemas.android.c ...

  8. android手机传感器总结

    传感器的分类 动作传感器 加速度传感器 重力传感器 陀螺仪 位置传感器 方向传感器 磁力传感器 环境传感器 温度传感器 压力传感器 亮度传感器 传感器的使用 1.获取SensorManager对象 2 ...

  9. Android传感器Motion Sensor开发实验

    目录 一.实验目的 二.实验要求 三.实验原理 (一)第一次实验 1.JDK(Java Development Kit) 2.Android SDK 3.AVD(Android Virtual Dev ...

最新文章

  1. 数十篇推荐系统论文被批无法复现:源码、数据集均缺失,性能难达预期
  2. vue页面绘图_利用vue制作在线涂鸦板
  3. 如何使用jlink从flash中读取数据保存为bin文件到本地
  4. 每日一博 - Java序列化一二事儿
  5. canal数据同步(客户端代码编写)
  6. SaaS权限控制:设计思路和表分析
  7. 宜昌宝塔河项目_宜昌城区首个垃圾分类定时定点投放点启用 厨余垃圾破袋投放...
  8. 【作品】超级玛丽射击版
  9. J2EE的13种核心技术简介
  10. 每日算法系列【LeetCode 1186】删除一次得到子数组最大和
  11. 安卓开发和python哪个难_入门IT该学Java还是Python?看完这篇你就懂了
  12. L1-049__056
  13. 【图像分割】基于matlab超像素SFFCM图像分割【含Matlab源码 1374期】
  14. 最新大数据案例分享:2019微信数据报告(图集)
  15. 腾讯云IM Web端支持发送语音消息
  16. 普渡大学的计算机工程,普渡大学(Purdue University)计算机工程专业解读 (2016-03-11 11:27:11)转载▼...
  17. 计算机磁盘管理分盘可以撤销吗,电脑磁盘出现随便分盘不合理,怎么样重新分盘...
  18. 【Python语法】X[:,0]和X[:,1] 什么意思?
  19. 在c语言中 auto的作用,c语言中auto是什么意思
  20. bim 模型web页面展示_一种基于BIM模型的Web端轻量化展示方法与流程

热门文章

  1. 大内存PDF文件转Word免费之道
  2. 哈希表构造与处理冲突方法
  3. pytorch transforms图像增强
  4. 12 More Effective C++—条款16/17 (2/8原理与延缓求值)
  5. 三国杀小游戏(C++)
  6. 北航计算机学院的博士待遇,北航博士毕业留校让人寒心的工资
  7. Java毕设项目-医药信息管理系统
  8. win10便签常驻桌面_超实用操作秘籍,小电教你玩转Win10系统功能!(下)
  9. 重生之我是赏金猎人-番外篇-记一次层层突破的攻防演练
  10. 能够创建时间循环并飞檐走壁的 VR 游戏 TRANSPOSE正式上线