微信搖一搖原理

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();
}
}
複製代碼

發佈了51 篇原創文章 · 獲贊 15 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章