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代码

packagecom.ray.test;

importAndroid.app.Activity;

importAndroid.os.Bundle;

importAndroid.hardware.SensorManager;

importAndroid.hardware.Sensor;

importAndroid.hardware.SensorEventListener;

importAndroid.hardware.SensorEvent;

publicclassSensorTestextendsActivity{

privateSensorManagersensorMgr;

Sensorsensor=sensorMgr.getDefaultSensor
(Sensor.TYPE_ACCELEROMETER);

privatefloatx,y,z;

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

sensorMgr=(SensorManager)
getSystemService(SENSOR_SERVICE);

SensorEventListenerlsn=newSensorEventListener(){

publicvoidonSensorChanged(SensorEvente){

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);

}

publicvoidonAccuracyChanged(Sensors,intaccuracy){

}

};

//注册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;

}
}
}
}

更多相关文章

  1. 【Android 笔记 五】 Android Sensor感应器介绍(一)重力感应加速度
  2. android 重力感应初步认识
  3. 【py交易】算法竞赛入门经典6.3.1 小球下落 python

随机推荐

  1. android studio 2.0 错误记录
  2. 音乐播放器源码
  3. android EOFException异常解决办法 (Share
  4. 快速的Android漏洞的审计工具
  5. Appium的简单使用(Android参数获取)
  6. 安卓常用参数笔记
  7. android的中的触感反馈
  8. Android(安卓)envsetup.sh剖析
  9. Android开发笔记
  10. android studio信鸽推送10004错误