摇一摇优化

来源:互联网 发布:淘宝一件代发怎么操作 编辑:程序博客网 时间:2024/05/16 08:07

1 简介

最近开发Android 摇一摇显示日志功能,结果发现,太敏感了,随便动一下手机就会震动,研究了一下这个问题,遂写这篇博客记录下来。

2 基本代码

(1) Android摇一摇就是利用加速度传感器来感知手机的方位,基本代码如下: 
MainActivity.Java

public class MainActivity extends AppCompatActivity {    private SensorManager sensorManager;    private Vibrator vibrator;    private ShakeListener shakeListener;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);        vibrator = (Vibrator) getSystemService(Service.VIBRATOR_SERVICE);        shakeListener = new ShakeListener();        sensorManager.registerListener(shakeListener, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), sensorManager.SENSOR_DELAY_NORMAL);    }    //摇一摇监听器    public class ShakeListener implements SensorEventListener {        @Override        public void onSensorChanged(SensorEvent event) {            //values[0]:X轴,values[1]:Y轴,values[2]:Z轴            float[] values = event.values;            if ((Math.abs(values[0]) > 15 || Math.abs(values[1]) > 15 || Math.abs(values[2]) > 15)) {                //摇动手机后,再伴随震动提示~~                vibrator.vibrate(500);            }        }        @Override        public void onAccuracyChanged(Sensor sensor, int accuracy) {        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

界面代码忽略不计,增加下面的权限:

 <uses-permission android:name="android.permission.VIBRATE"/>    <uses-permission android:name="android.hardware.sensor.accelerometer"/>
  • 1
  • 2
  • 1
  • 2

(2) 代码解释

sensorManager.registerListener(shakeListener, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), sensorManager.SENSOR_DELAY_NORMAL);
  • 1
  • 1

第一个参数是监听器 
第二个参数是传感器类型,Sensor.TYPE_ACCELEROMETER 表示加速度传感器 
第三个参数是回调的频率,sensorManager.SENSOR_DELAY_NORMAL 表示正常速度

(3) 方向解释

public void onSensorChanged(SensorEvent event) {            //values[0]:X轴,values[1]:Y轴,values[2]:Z轴            float[] values = event.values;            if ((Math.abs(values[0]) > 15 || Math.abs(values[1]) > 15 || Math.abs(values[2]) > 15)) {                //摇动手机后,再伴随震动提示~~                vibrator.vibrate(500);            }        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

float[] values = event.values;有三个值,分别表示x,y,z上的偏移量 
用网上的图来解释一下x,y,z的含义:

这里写图片描述

把手机平放在桌面上,然后从右边向左边翻过来,盖在桌面上,这个过程z的值从正数到负数

把手机平方在桌面上,然后把头抬起来,Y值是正数,不断变大;然后把尾部台起来,Y值是负数,绝对值不断变大

把手机竖直拿在手中,屏幕正对自己,然后向左倾斜,注意是倾斜不是平移,x的值是正数,不断变大;向右倾斜,x是负数,绝对值不断变大

3 问题

这样写的代码是有问题的,太灵敏了,只要一动就会震动,打出日志一看,onSensorChanged()是在不停的回调的,如果竖直拿着手机,向左倾斜,然后保持不动,你会发现 x 的值基本不变,而且是个很大的值,这样就不停的在震动,显然这不是摇一摇。

怎么办呢? 
后来参考了iOS,问了ios的摇一摇是怎么实现的,原来ios把一次摇动的变化过程作为一个事件,由系统发给你,也就是说你只有动了,有个变化过程,它才给你事件,而且只给一个,不像Android,尼玛,不停的告诉你。

解决的思路找到了,我们判断的条件不应该是最大值,而应该是变化的快慢,也就是速度,换句话说,我们要计算摇动的速度,通过x,y,z计算空间移动的距离,除以移动时间,就得到了速度,好吧,太复杂了,直接上代码

4 解决方法

判断摇动的速度,而不是摇动后的左标是否达到某一个值 
正确的代码如下:

public class MainActivity extends AppCompatActivity {    private SensorManager sensorManager;    private Vibrator vibrator;    private ShakeListener shakeListener;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);        vibrator = (Vibrator) getSystemService(Service.VIBRATOR_SERVICE);        shakeListener = new ShakeListener();        sensorManager.registerListener(shakeListener, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), sensorManager.SENSOR_DELAY_NORMAL);    }    //摇一摇监听器    public class ShakeListener implements SensorEventListener {        /**         * 检测的时间间隔         */        static final int UPDATE_INTERVAL = 100;        /**         * 上一次检测的时间         */        long mLastUpdateTime;        /**         * 上一次检测时,加速度在x、y、z方向上的分量,用于和当前加速度比较求差。         */        float mLastX, mLastY, mLastZ;        /**         * 摇晃检测阈值,决定了对摇晃的敏感程度,越小越敏感。         */        public int shakeThreshold = 4000;        @Override        public void onSensorChanged(SensorEvent event) {            long currentTime = System.currentTimeMillis();            long diffTime = currentTime - mLastUpdateTime;            if (diffTime < UPDATE_INTERVAL) {                return;            }            mLastUpdateTime = currentTime;            float x = event.values[0];            float y = event.values[1];            float z = event.values[2];            float deltaX = x - mLastX;            float deltaY = y - mLastY;            float deltaZ = z - mLastZ;            mLastX = x;            mLastY = y;            mLastZ = z;            float delta = (float) (Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ) / diffTime * 10000);            // 当加速度的差值大于指定的阈值,认为这是一个摇晃            if (delta > shakeThreshold) {                vibrator.vibrate(200);            }        }        @Override        public void onAccuracyChanged(Sensor sensor, int accuracy) {        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66

经过测试,这段代码很好的实现了摇一摇功能。

0 0
原创粉丝点击