Android重力感應實現方式簡介
本文段轉自:http://developer.51cto.com/art/201001/180956.htm
在Android應用程序的開發中,占據主要地位的當屬游戲的開發。我們在這篇文章中將會針對在游戲中需要用到的重力感應功能,來為大家詳細分析Android重力感應的實現方法,以幫助大家解決相關問題。
Android中的很多游戲的游戲都使用了重力感應的技術,但其api demo卻並沒有重力感應的實例(不知道是不是我沒找到,找到的朋友麻煩告訴我一下,謝謝),因為開發的需要,就研究了一下重力感應這方面,因為網上關於這方面的東西比較少,所以寫出來跟大家交流一下,算是拋磚引玉吧。(ps.因為重力感應式需要真機才能測試的,所以,下面提供的demo程序只能在真機上跑。)
因為官方說明比較含糊難懂,我用最簡單的方式講一下Android重力感應系統的坐標系
以屏幕的左下方為原點(2d編程的時候,是以屏幕左上方為原點的,這個值得注意一下),箭頭指向的方向為正。
從-10到10,以浮點數為等級單位,想象一下以下情形:
手機屏幕向上(z軸朝天)水平放置的時侯,(x,y,z)的值分別為(0,0,10);
手機屏幕向下(z軸朝地)水平放置的時侯,(x,y,z)的值分別為(0,0,-10);
手機屏幕向左側放(x軸朝天)的時候,(x,y,z)的值分別為(10,0,0);
手機豎直(y軸朝天)向上的時候,(x,y,z)的值分別為(0,10,0);
其他的如此類推,規律就是:朝天的就是正數,朝地的就是負數。利用x,y,z三個值求三角函數,就可以精確檢測手機的運動狀態了。
接下來,用最短的代碼完成Android重力感應功能,程序效果就是在title上面輸出x,y,z的值。
Java代碼
package com.ray.test;
import Android.app.Activity;
import Android.os.Bundle;
import Android.hardware.SensorManager;
import Android.hardware.Sensor;
import Android.hardware.SensorEventListener;
import Android.hardware.SensorEvent;
public class SensorTest extends Activity {
private SensorManager sensorMgr;
Sensor sensor = sensorMgr.getDefaultSensor
(Sensor.TYPE_ACCELEROMETER);
private float x, y, z;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sensorMgr = (SensorManager)
getSystemService(SENSOR_SERVICE);
SensorEventListener lsn = new SensorEventListener() {
public void onSensorChanged(SensorEvent e) {
x = e.values[SensorManager.DATA_X];
y = e.values[SensorManager.DATA_Y];
z = e.values[SensorManager.DATA_Z];
setTitle("x="+(int)x+","+"y="+(int)y+","+"z="+(int)z);
}
public void onAccuracyChanged(Sensor s, int accuracy) {
}
};
//注冊listener,第三個參數是檢測的精確度
sensorMgr.registerListener(lsn, sensor,
SensorManager.SENSOR_DELAY_GAME);
}
}
本文段:Android日記之2012/02/16——淺談Android重力感應
轉自:http://blog.csdn.net/zhuweijun/article/details/7265666
重力感應,也算是智能機和非智能機的區別之一了吧,Android設備中自然也能有這個功能。
在Android中,使用重力感應功能需要使用SensorEventListener,其中有兩個方法, onSensorChanged和onAccuracyChanged,一般都是在onSensorChanged方法中做一些希望達到的效果處理(慚愧,才剛接觸這個重力感應,所以對這兩個方法也不是很了解)。重力感應是感應的一種方式,因此,我們還要用到感應檢測包Sensor。
首先,我們要獲得一個SensorManager,SensorManager manager = (SensorManager) this.getSystemService(Context.SENSOR_SERVICE)。然后,再通過這個manager來獲得一個Sensor 的列表,List<Sensor> sensors = manager.getSensorList(Sensor.TYPE_ACCELEROMETER)。 Sensor.TYPE_ACCELEROMETER就是指加速度感應檢測,當然還有一些其他的感應檢測,這邊就沒必要都說一下了。
我在做重力感應的時候,用的是manager.registerListener(listener, sensor, rate),這邊的sensor就是sensors中的一個Sensor,rate是指延遲時間。
如果要取消這個重力感應的話,就manager.unregisterListener(listener)來取消注冊就行了。
public class SensorEventDemoActivity extends Activity implements SensorEventListener{
private List<Sensor> sensors;
private Sensor sensor;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
protected void onResume() {
super.onResume();
SensorManager manager = (SensorManager) this.getSystemService(Context.SENSOR_SERVICE);
sensors = manager.getSensorList(Sensor.TYPE_ACCELEROMETER);
sensor = sensors.get(0);
manager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME);
}
@Override
public void onSensorChanged(SensorEvent event) {
Log.d("Sensor Demo", "do sensor");
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
其實,代碼很簡單,主要就是要看在實際項目中如何運用了。
Android重力感應的相關實現方法就為大家介紹到這里。
本文段:Android 小球重力感應實現(三)
http://www.eoeandroid.com/thread-98312-1-1.html
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
import android.view.WindowManager;
import android.view.SurfaceHolder.Callback;
public class SurfaceViewAcitvity extends Activity {
MyView mAnimView = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 全屏顯示窗口
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
//強制橫屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
// 顯示自定義的游戲View
mAnimView = new MyView(this);
setContentView(mAnimView);
}
public class MyView extends SurfaceView implements Callback,Runnable ,SensorEventListener{
/**每50幀刷新一次屏幕**/
public static final int TIME_IN_FRAME = 50;
/** 游戲畫筆 **/
Paint mPaint = null;
Paint mTextPaint = null;
SurfaceHolder mSurfaceHolder = null;
/** 控制游戲更新循環 **/
boolean mRunning = false;
/** 游戲畫布 **/
Canvas mCanvas = null;
/**控制游戲循環**/
boolean mIsRunning = false;
/**SensorManager管理器**/
private SensorManager mSensorMgr = null;
Sensor mSensor = null;
/**手機屏幕寬高**/
int mScreenWidth = 0;
int mScreenHeight = 0;
/**小球資源文件越界區域**/
private int mScreenBallWidth = 0;
private int mScreenBallHeight = 0;
/**游戲背景文件**/
private Bitmap mbitmapBg;
/**小球資源文件**/
private Bitmap mbitmapBall;
/**小球的坐標位置**/
private float mPosX = 200;
private float mPosY = 0;
/**重力感應X軸 Y軸 Z軸的重力值**/
private float mGX = 0;
private float mGY = 0;
private float mGZ = 0;
public MyView(Context context) {
super(context);
/** 設置當前View擁有控制焦點 **/
this.setFocusable(true);
/** 設置當前View擁有觸摸事件 **/
this.setFocusableInTouchMode(true);
/** 拿到SurfaceHolder對象 **/
mSurfaceHolder = this.getHolder();
/** 將mSurfaceHolder添加到Callback回調函數中 **/
mSurfaceHolder.addCallback(this);
/** 創建畫布 **/
mCanvas = new Canvas();
/** 創建曲線畫筆 **/
mPaint = new Paint();
mPaint.setColor(Color.WHITE);
/**加載小球資源**/
mbitmapBall = BitmapFactory.decodeResource(this.getResources(), R.drawable.ball);
/**加載游戲背景**/
mbitmapBg = BitmapFactory.decodeResource(this.getResources(), R.drawable.bg);
/**得到SensorManager對象**/
mSensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);
mSensor = mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
// 注冊listener,第三個參數是檢測的精確度
//SENSOR_DELAY_FASTEST 最靈敏 因為太快了沒必要使用
//SENSOR_DELAY_GAME 游戲開發中使用
//SENSOR_DELAY_NORMAL 正常速度
//SENSOR_DELAY_UI 最慢的速度
mSensorMgr.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_GAME);
}
private void Draw() {
/**繪制游戲背景**/
mCanvas.drawBitmap(mbitmapBg,0,0, mPaint);
/**繪制小球**/
mCanvas.drawBitmap(mbitmapBall, mPosX,mPosY, mPaint);
/**X軸 Y軸 Z軸的重力值**/
mCanvas.drawText("X軸重力值 :" + mGX, 0, 20, mPaint);
mCanvas.drawText("Y軸重力值 :" + mGY, 0, 40, mPaint);
mCanvas.drawText("Z軸重力值 :" + mGZ, 0, 60, mPaint);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
/**開始游戲主循環線程**/
mIsRunning = true;
new Thread(this).start();
/**得到當前屏幕寬高**/
mScreenWidth = this.getWidth();
mScreenHeight = this.getHeight();
/**得到小球越界區域**/
mScreenBallWidth = mScreenWidth - mbitmapBall.getWidth();
mScreenBallHeight = mScreenHeight - mbitmapBall.getHeight();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mIsRunning = false;
}
@Override
public void run() {
while (mIsRunning) {
/** 取得更新游戲之前的時間 **/
long startTime = System.currentTimeMillis();
/** 在這里加上線程安全鎖 **/
synchronized (mSurfaceHolder) {
/** 拿到當前畫布 然后鎖定 **/
mCanvas = mSurfaceHolder.lockCanvas();
Draw();
/** 繪制結束后解鎖顯示在屏幕上 **/
mSurfaceHolder.unlockCanvasAndPost(mCanvas);
}
/** 取得更新游戲結束的時間 **/
long endTime = System.currentTimeMillis();
/** 計算出游戲一次更新的毫秒數 **/
int diffTime = (int) (endTime - startTime);
/** 確保每次更新時間為50幀 **/
while (diffTime <= TIME_IN_FRAME) {
diffTime = (int) (System.currentTimeMillis() - startTime);
/** 線程等待 **/
Thread.yield();
}
}
}
@Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
@Override
public void onSensorChanged(SensorEvent event) {
mGX = event.values[SensorManager.DATA_X];
mGY= event.values[SensorManager.DATA_Y];
mGZ = event.values[SensorManager.DATA_Z];
//這里乘以2是為了讓小球移動的更快
mPosX -= mGX * 2;
mPosY += mGY * 2;
//檢測小球是否超出邊界
if (mPosX < 0) {
mPosX = 0;
} else if (mPosX > mScreenBallWidth) {
mPosX = mScreenBallWidth;
}
if (mPosY < 0) {
mPosY = 0;
} else if (mPosY > mScreenBallHeight) {
mPosY = mScreenBallHeight;
}
}
}
}