zoukankan      html  css  js  c++  java
  • [转]浅谈Android重力感应

    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;

    }
    }
    }
    }

  • 相关阅读:
    安卓开发之有序广播
    安卓开发之无序广播
    安卓开发之短信发送器的开发
    安卓开发之隐式意图与显示意图
    安卓root权限 被提示Read-only file system 或 Operation not permitted 解决方案
    gcc 的基本使用和静态库、动态库的制作与使用
    Python类的学习,看这一篇文章就够了!
    Qt 添加程序图标和系统托盘图标
    Qt ListWidget item 发起拖放
    Qt 接受拖放
  • 原文地址:https://www.cnblogs.com/freeliver54/p/2831043.html
Copyright © 2011-2022 走看看