Android学习指南之三十七:Android传感器编程


-

本节教程主要讲解Android传感器编程的基础知识,包括加速度传感器(accelerometer)、陀螺仪(gyroscope)、环境光照传感器(light)、磁力传感器(magnetic field)、方向传感器(orientation)、压力传感器(pressure)、距离传感器(proximity)和温度传感器(temperature)。

一、前言

我很喜欢电脑,可是笔记本还是太大,笔记本电脑再小还是要弄个小包背起来的,智能手机则不同,它完全就是一个手机,可以随意装在一个口袋里随身携带。因此我在2002年左右时最喜欢玩装备是Dell的PDA,2007年的时候最喜欢玩的是N73,而在2010年最喜欢玩的则是Milestone。眼见着手机的功能越来越强,时至今日智能手机甚至在某些方面已经强过了台式机和笔记本。本节课讲的就是智能手机强过台式机和笔记本的地方:传感器。

  2008年的时候我很喜欢我的小白笔记本Macbook,喜欢玩它的一个小软件,一拍桌子,笔记本感受到了震动,它就转换了一个桌面出来,这让我像个小孩子一样没事就拍拍桌子。这一功能这得益于苹果笔记本内置有传感器。

  我不知道iPhone手机是不是第一个把各种各样的传感器运用在手机上的,不过我知道iPhone是把传感器运用在手机上最成功的第一个。随后的Android系统也内置了大量的传感器,这让Android系统手机和普通的诺基亚智能机和Windows CE智能机相比牛气了许多,在拥有了Milestone之后,我的N73就被仍在抽屉的角落里了。

  从Android1.5开始,系统内置了对多达八种传感器的支持,他们分别是:加速度传感器(accelerometer)、陀螺仪(gyroscope)、环境光照传感器(light)、磁力传感器(magnetic field)、方向传感器(orientation)、压力传感器(pressure)、距离传感器(proximity)和温度传感器(temperature)。

  利用这些传感器我们可以制作出各种有趣的应用程序和游戏。譬如在口袋里晃一晃手机,手机就开始神不知鬼不觉的录音,不要着急这个很容易做,我们在本文的结尾就一起制作这个小应用。

  本讲的学习方式还是在实战中学习,需要提醒的是模拟器中无法模拟传感器,因此你需要准备一款Android真机才能运行本讲的例子。

  二、实例:手机传感器清单

我们还是先看程序后解释。

1、创建一个项目 Lesson37_HelloSensor ,主Activity名字叫 mainActivity.java。

2、UI布局文件main.xml的内容如下:


XML/HTML代码
<?xml version="1.0" encoding="utf-8"?>
<linearlayout android:layout_height="fill_parent" android:layout_width="fill_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android">
<textview android:layout_height="wrap_content" android:layout_width="fill_parent" android:text="" android:id="@+id/TextView01">
</textview></linearlayout>

3、mainActivity.java的内容如下:


Java代码
package basic.android.lesson37;

import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

//准备显示信息的UI组建
final TextView tx1 = (TextView) findViewById(R.id.TextView01);

//从系统服务中获得传感器管理器
SensorManager sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

//从传感器管理器中获得全部的传感器列表
List<sensor> allSensors = sm.getSensorList(Sensor.TYPE_ALL);

//显示有多少个传感器
tx1.setText("经检测该手机有" + allSensors.size() + "个传感器,他们分别是:\n");

//显示每个传感器的具体信息
for (Sensor s : allSensors) {

String tempString = "\n" + " 设备名称:" + s.getName() + "\n" + " 设备版本:" + s.getVersion() + "\n" + " 供应商:"
+ s.getVendor() + "\n";

switch (s.getType()) {
case Sensor.TYPE_ACCELEROMETER:
tx1.setText(tx1.getText().toString() + s.getType() + " 加速度传感器accelerometer" + tempString);
break;
case Sensor.TYPE_GYROSCOPE:
tx1.setText(tx1.getText().toString() + s.getType() + " 陀螺仪传感器gyroscope" + tempString);
break;
case Sensor.TYPE_LIGHT:
tx1.setText(tx1.getText().toString() + s.getType() + " 环境光线传感器light" + tempString);
break;
case Sensor.TYPE_MAGNETIC_FIELD:
tx1.setText(tx1.getText().toString() + s.getType() + " 电磁场传感器magnetic field" + tempString);
break;
case Sensor.TYPE_ORIENTATION:
tx1.setText(tx1.getText().toString() + s.getType() + " 方向传感器orientation" + tempString);
break;
case Sensor.TYPE_PRESSURE:
tx1.setText(tx1.getText().toString() + s.getType() + " 压力传感器pressure" + tempString);
break;
case Sensor.TYPE_PROXIMITY:
tx1.setText(tx1.getText().toString() + s.getType() + " 距离传感器proximity" + tempString);
break;
case Sensor.TYPE_TEMPERATURE:
tx1.setText(tx1.getText().toString() + s.getType() + " 温度传感器temperature" + tempString);
break;
default:
tx1.setText(tx1.getText().toString() + s.getType() + " 未知传感器" + tempString);
break;
}
}

}
}</sensor>

4、连接真机Milestone,编译并运行程序,显示结果如下:

5、结合上面的程序我们做一些解释。

1)Android所有的传感器都归传感器管理器 SensorManager 管理,获取传感器管理器的方法很简单:

String service_name = Context.SENSOR_SERVICE;

SensorManager sensorManager = (SensorManager)getSystemService(service_name);

2)现阶段Android支持的传感器有8种,它们分别是:


传感器类型常量


内部整数值


中文名称


Sensor.TYPE_ACCELEROMETER

1


加速度传感器


Sensor.TYPE_MAGNETIC_FIELD

2


磁力传感器


Sensor.TYPE_ORIENTATION

3


方向传感器


Sensor.TYPE_GYROSCOPE

4


陀螺仪传感器


Sensor.TYPE_LIGHT

5


环境光照传感器


Sensor.TYPE_PRESSURE

6


压力传感器


Sensor.TYPE_TEMPERATURE

7


温度传感器


Sensor.TYPE_PROXIMITY

8

距离传感器


3)从传感器管理器中获取其中某个或者某些传感器的方法有如下三种:

第一种:获取某种传感器的默认传感器

Sensor defaultGyroscope = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);

第二种:获取某种传感器的列表

List<Sensor> pressureSensors = sensorManager.getSensorList(Sensor.TYPE_PRESSURE);

第三种:获取所有传感器的列表,我们这个例子就用的第三种

List<Sensor> allSensors = sensorManager.getSensorList(Sensor.TYPE_ALL);

4)对于某一个传感器,它的一些具体信息的获取方法可以见下表:


方法


描述


getMaximumRange()


最大取值范围


getName()


设备名称


getPower()


功率


getResolution()


精度


getType()


传感器类型


getVentor()


设备供应商


getVersion()

设备版本号


三、实例:窈窈录音器

通过上面的例子我们学会了如何获得某种类型的传感器,下面我通过一个实例来学会如何使用某一个类型的传感器。我们这里使用加速度传感器来实现这样一个功能:开启我们的录音程序放在你的口袋或者提包里,需要录音的时候把衣服整理一下,或者把提包挪动个位置,那么此时手机就会感受到变化从而开始录音。由此达到神不知鬼不觉的录音效果。说起来似乎有点神,其实做起来很简单,让我们开始吧。

简单的录音程序已经在第28讲的时候做过了,我们在28讲程序的基础上写本讲的代码。

1、新建一个项目 Lesson37_YYRecorder ,主文件叫 MainActivity.java ,具体信息都可以参见第二十八讲的“窈窈录音”的例子。

2、这里只贴出于28讲不同的 MainActivity.java 的代码,请注意看注释:


Java代码
package basic.android.lesson37;

import java.io.File;
import java.io.IOException;
import java.util.Calendar;
import java.util.Locale;

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.media.MediaRecorder;
import android.os.Bundle;
import android.text.format.DateFormat;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {

//录音和停止按钮
private Button recordButton;
private Button stopButton;

//检测摇动相关变量
private long initTime = 0;
private long lastTime = 0;
private long curTime = 0;
private long duration = 0;

private float last_x = 0.0f;
private float last_y = 0.0f;
private float last_z = 0.0f;

private float shake = 0.0f;
private float totalShake = 0.0f;

//媒体录音器对象
private MediaRecorder mr;

//是否正在录音
private boolean isRecoding = false;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

// UI组件
recordButton = (Button) this.findViewById(R.id.Button01);
stopButton = (Button) this.findViewById(R.id.Button02);
final TextView tx1 = (TextView) this.findViewById(R.id.TextView01);

// 录音按钮点击事件
recordButton.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
//如果没有在录音,那么点击按钮可以开始录音
if(!isRecoding){
startRecord();
}
}
});

// 停止按钮点击事件
stopButton.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
initShake();
//如果正在录音,那么可以停止录音
if (mr != null) {
mr.stop();
mr.release();
mr = null;
recordButton.setText("录音");
Toast.makeText(getApplicationContext(), "录音完毕", Toast.LENGTH_LONG).show();
isRecoding = false;

}
}
});

// 获取传感器管理器
SensorManager sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
// 获取加速度传感器
Sensor acceleromererSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

// 定义传感器事件监听器
SensorEventListener acceleromererListener = new SensorEventListener() {

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
//什么也不干
}

//传感器数据变动事件
@Override
public void onSensorChanged(SensorEvent event) {

//如果没有开始录音的话可以监听是否有摇动事件,如果有摇动事件可以开始录音
if(!isRecoding){
//获取加速度传感器的三个参数
float x = event.values[SensorManager.DATA_X];
float y = event.values[SensorManager.DATA_Y];
float z = event.values[SensorManager.DATA_Z];

//获取当前时刻的毫秒数
curTime = System.currentTimeMillis();

//100毫秒检测一次
if ((curTime - lastTime) > 100) {

duration = (curTime - lastTime);

// 看是不是刚开始晃动
if (last_x == 0.0f && last_y == 0.0f && last_z == 0.0f) {
//last_x、last_y、last_z同时为0时,表示刚刚开始记录
initTime = System.currentTimeMillis();
} else {
// 单次晃动幅度
shake = (Math.abs(x - last_x) + Math.abs(y - last_y) + Math.abs(z - last_z)) / duration * 100;
}

//把每次的晃动幅度相加,得到总体晃动幅度
totalShake += shake;

// 判断是否为摇动,这是我自己写的标准,不准确,只是用来做教学示例,别误会了^_^
if (totalShake > 10 && totalShake / (curTime - initTime) * 1000 > 10) {
startRecord();
initShake();
}

tx1.setText("总体晃动幅度="+totalShake+ "\n平均晃动幅度="+totalShake / (curTime - initTime) * 1000 );
}

last_x = x;
last_y = y;
last_z = z;
lastTime = curTime;
}
}

};

//在传感器管理器中注册监听器
sm.registerListener(acceleromererListener, acceleromererSensor, SensorManager.SENSOR_DELAY_NORMAL);

}

// 开始录音
public void startRecord() {
//把正在录音的标志设为真
isRecoding = true;
//存放文件
File file = new File("/sdcard/" + "YY"
+ new DateFormat().format("yyyyMMdd_hhmmss", Calendar.getInstance(Locale.CHINA)) + ".amr");

Toast.makeText(getApplicationContext(), "正在录音,录音文件在" + file.getAbsolutePath(), Toast.LENGTH_LONG).show();

// 创建录音对象
mr = new MediaRecorder();

// 从麦克风源进行录音
mr.setAudioSource(MediaRecorder.AudioSource.DEFAULT);

// 设置输出格式
mr.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);

// 设置编码格式
mr.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);

// 设置输出文件
mr.setOutputFile(file.getAbsolutePath());

try {
// 创建文件
file.createNewFile();
// 准备录制
mr.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// 开始录制
mr.start();
recordButton.setText("录音中……");
}

//摇动初始化
public void initShake() {
lastTime = 0;
duration = 0;
curTime = 0;
initTime = 0;
last_x = 0.0f;
last_y = 0.0f;
last_z = 0.0f;
shake = 0.0f;
totalShake = 0.0f;
}
}

3、连接真机Milestone,编译并运行程序:

晃动机器,开始录音。

查看录音文件,效果还可以:

4、我们小结一下:到Android2.2版本为止,系统并没有给开发者提供多少可用的包装好的传感器信息,只是提供了传感器发出的原始数据,这些原始数据存放在 event.values 的数组里,开发人员需要从这些裸数据总自行发掘有用的信息,譬如从加速度传感器的3维裸数据中获得摇动的判断(我的摇动判断很弱智,有时间再改吧……)。好了本讲就先到这里,关于传感器有机会我们展开再谈,下次再见吧。
本文来源于Android开发网 http://www.jizhuomi.com/android/ , 原文地址:http://www.jizhuomi.com/android/course/258.html

更多相关文章

  1. Android(安卓)传感器概述
  2. Android(安卓)screenOrientation 屏幕方向的设定与控制
  3. android:screenOrientation属性
  4. Unity调用Android录音
  5. Android(安卓)麦克风录音动画
  6. Unity调用Android录音
  7. Android传感器
  8. 《IT蓝豹》吹雪花demo,学习android传感器
  9. Android录音应用

随机推荐

  1. 黑马程序员之手机卫士第八天
  2. Android(安卓)EditView 获取焦点 不弹出
  3. Android(安卓)ListView xml配置
  4. android 图片自动切换
  5. Android应用开发相关下载资源
  6. 【30篇突击 android】源码统计 十
  7. android 入门xml布局文件--转
  8. android:windowSoftInputMode属性使用
  9. android无线调试
  10. Android在开机时自动启动一个应用程序