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(安卓)Sensor Shake(WeChat)
  2. android传感器总结
  3. Android(安卓)弹球游戏
  4. Android7.0中文文档(API)-- LinearLayout.LayoutParams
  5. 【Android(安卓)笔记 五】 Android(安卓)Sensor感应器介绍(一)重力
  6. Android(安卓)禁止横竖屏切换
  7. android: layout_gravity VS android: gravity
  8. android 重力感应初步认识
  9. Android界面布局之gravity

随机推荐

  1. Windows环境下Android(安卓)Studio系列3
  2. Android(安卓)Studio使用gradle-experime
  3. Android(安卓)数据库框架GreenDao与LiteP
  4. android UiAutomator利用am命令启动和结
  5. android透明activity
  6. Android(安卓)升级 SDK,安装4.0及以上SDK
  7. android:View.setTag()与View.getTag()的
  8. android 标题栏不显示?
  9. android singleTask使用情况,场景分析
  10. Android(安卓)Audio代码分析7 - stream t