微信摇一摇原理(Sensor传感器的一些心得)(转http://www.cnblogs.com/chungeguo/archive/2012/01/13/2321916.html)

Coordinator
Apr 17, 2012 at 12:43 PM

 

1、传感器(Sensor)是什么?

传感器是能标识温度,加速度等等物理现象的转换电子信号的机器。Android SDK,在移动设备中提供了各种各样的传感器的API。

  

2、传感器类型

方向、加速表、光线、磁场、临近性、温度等。

 

3、SensorListener 接口是传感器应用程序的中心,它包括两个必需方法:

 

  • onSensorChanged(int sensor,float values[]) 方法在传感器值更改时调用。该方法只对受此应用程序监视的传感器调用(更多内容见下文)。该方法的参数包括:一个整数,指示更改的传感器;一个浮点值数组,表示传感器数据本身。有些传感器只提供一个数据值,另一些则提供三个浮点值。方向和加速表传感器都提供三个数据值。
  • 当传感器的准确性更改时,将调用 onAccuracyChanged(int sensor,int accuracy) 方法。参数包括两个整数:一个表示传感器,另一个表示该传感器新的准确值。

4、onResume() 方法使用对 SensorManager 的引用通过 registerListener 方法注册传感器更新:

 

  • 第一个参数是实现 SensorListener 接口的类的实例。
  • 第二个参数是所需传感器的位掩码。在本例中,应用程序从 SENSOR_ORIENTATION  SENSOR_ACCELEROMETER 请求数据。
  • 第三个参数是一个系统提示,指出应用程序更新传感器值所需的速度。

 

应用程序(活动)暂停后,需要注销侦听器,这样以后就不会再收到传感器更新。这通过 SensorManager  unregisterListener 方法实现。惟一的参数是 SensorListener 的实例。

SensorListener 必须实现两个方法 onSensorChange  onAccuracyChanged。示例应用程序不关心传感器的准确度,但关注传感器当前的 X、Y 和 Z 值。onAccuracyChanged 方法实质上不执行任何操作;它只在每次调用时添加一个日志项。

 

似乎经常需要调用 onSensorChanged 方法,因为加速表和方向传感器正在快速发送数据。查看第一个参数确定哪个传感器在发送数据。确认了发送数据的传感器之后,将使用方法第二个参数传递的浮点值数组中所包含的数据更新相应的 UI 元素。该示例只是显示这些值,但在更加高级的应用程序中,还可以分析这些值,比较原来的值,或者设置某种模式识别算法来确定用户(或外部环境)的行为。

 

package wuba.shakedemo.guocg;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.hardware.SensorManager;
import android.hardware.SensorListener;
public class Sensor extends Activity implements SensorListener {
final String tag = "IBMEyes";
SensorManager sm = null;
TextView xViewA = null;
TextView yViewA = null;
TextView zViewA = null;
TextView xViewO = null;
TextView yViewO = null;
TextView zViewO = null;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// get reference to SensorManager
sm = (SensorManager) getSystemService(SENSOR_SERVICE);
setContentView(R.layout.main);
xViewA = (TextView) findViewById(R.id.xbox);
yViewA = (TextView) findViewById(R.id.ybox);
zViewA = (TextView) findViewById(R.id.zbox);
xViewO = (TextView) findViewById(R.id.xboxo);
yViewO = (TextView) findViewById(R.id.yboxo);
zViewO = (TextView) findViewById(R.id.zboxo);
}
public void onSensorChanged(int sensor, float[] values) {
synchronized (this) {
Log.d(tag, "onSensorChanged: " + sensor + ", x: " +
values[0] + ", y: " + values[1] + ", z: " + values[2]);
if (sensor == SensorManager.SENSOR_ORIENTATION) {
xViewO.setText("Orientation X: " + values[0]);
yViewO.setText("Orientation Y: " + values[1]);
zViewO.setText("Orientation Z: " + values[2]);
}
if (sensor == SensorManager.SENSOR_ACCELEROMETER) {
xViewA.setText("Accel X: " + values[0]);
yViewA.setText("Accel Y: " + values[1]);
zViewA.setText("Accel Z: " + values[2]);
}
}
}

public void onAccuracyChanged(int sensor, int accuracy) {
Log.d(tag,"onAccuracyChanged: " + sensor + ", accuracy: " + accuracy);
}
@Override
protected void onResume() {
super.onResume();
// register this class as a listener for the orientation and accelerometer sensors
sm.registerListener(this,
SensorManager.SENSOR_ORIENTATION |SensorManager.SENSOR_ACCELEROMETER,
SensorManager.SENSOR_DELAY_NORMAL);
}

@Override
protected void onStop() {
// unregister listener
sm.unregisterListener(this);
super.onStop();
}
}

 

5、微信通过摇晃手中的手机就能知道现在多少人在线,这确实是一个非常好的方法,能很方便的联系到正在同时玩手机的朋友。这个原理是手机里面集成的加速度传感器,它能够分别测量X、Y、Z三个方面的加速度值,X方向值的大小代表手机水平移动,Y方向值的大小代表手机垂直移动,Z方向值的大小代表手机的空间垂直方向,天空的方向为正,地球的方向为负,然后把相关的加速度值传输给操作系统,通过判断其大小变化,就能知道同时玩微信的朋友了。

 

 

package boke.sensor.yao;

import com.se.yao.R;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;

public class SeActivity extends Activity {
SensorManager sm;
SensorL listener;

private boolean isRefresh=false;

Dialog d;

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

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

listener = new SensorL();
// 对加速计进行监听
sm.registerListener(listener, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_FASTEST);
// sm.registerListener(listener,
// sm.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),SensorManager.SENSOR_DELAY_FASTEST);
// sm.registerListener(listener,sm.getDefaultSensor(Sensor.TYPE_PRESSURE),SensorManager.SENSOR_DELAY_FASTEST);

AlertDialog.Builder b = new Builder(this);
// 用来显示的对话框
d = b.setPositiveButton("ok", new OnClickListener() {

@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
isRefresh = false;
dialog.cancel();
}
}).setMessage("摇到了.................").create();

}

private class SensorL implements SensorEventListener {

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub

}

@Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
// 判断是否在刷新
if (isRefresh)
return;
float newX = Math.abs(event.values[SensorManager.DATA_X]);
float newY = Math.abs(event.values[SensorManager.DATA_Y]);
float newZ = Math.abs(event.values[SensorManager.DATA_Z]);
// 这里是关键,判断某个方向上的加速度值是否达到自己想要的值
// X
if (newX >= 18) {
Toast.makeText(SeActivity.this, "newX" + newX, 0).show();
isRefresh = true;
d.show();
return;
}
// Y
if (newY >= 20) {
Toast.makeText(SeActivity.this, "newY" + newY, 0).show();
isRefresh = true;
d.show();
return;
}
// Z
if (newZ >= 20) {
Toast.makeText(SeActivity.this, "newZ" + newZ, 0).show();
isRefresh = true;
d.show();
return;
}

}
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
// Log.e("TYPE_MAGNETIC_FIELD", ""+event.sensor.toString());
}
if (event.sensor.getType() == Sensor.TYPE_PRESSURE) {
// Log.e("TYPE_PRESSURE", ""+event.sensor.toString());
}
}

}

@Override
protected void onPause() {
// ACTIVITY消失时取消监听
sm.unregisterListener(listener);
super.onPause();
}
}