[lottery] 03_双色球选号(三)——摇晃手机

Android 4.0

双色球选号(三)——摇晃手机

摇晃手机:
①屏蔽不同性能手机采样的差距
高性能:30ms采样一次数据
低性能:50ms采样一次数据
如何屏蔽?
每隔100ms采样一次,
高性能手机:第四次,也就是120ms采样一次
低性能手机:第二次,采样一次
1、初始化SensorManager
2、在onResume()时,注册sensor
3、在onPause()时,取消注册sensor
4、采用加速度数据
5、当累加数据达到一个阈值,就认为用户在摇晃手机,那么获取一注球,然后手机震动提醒用户获取成功
6、权限
<uses-permission android:name="android.permission.VIBRATE"/>  
7、全屏,防止屏幕切换
application:android:theme="@android:style/Theme.Light.NoTitleBar"  
activity:android:configChanges="keyboardHidden|orientation|screenLayout|smallestScreenSize"  
8、选多个球时候,注数自动增加
9、排列数和组合数
核心代码:
private SensorManager sensorManager;
private ShakeListener mySensorEventListener;
/**
 * 初始化Sensor相关操作
 */
public void initSensor(){
    //List<Sensor> sensorList = sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
    sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
    mySensorEventListener = new ShakeListener(context) {
        @Override
        public void createLottery() {
            // 机选红球
            randomSelectRedBall();
            // 机选蓝球
            randomSelectBlueBall();
        }
    };
}
/**
 * 注册Sensor
 */
public void registerSensor(){
    if (sensorManager != null) {
        Sensor sensor = sensorManager.getDefaultSensor( Sensor.TYPE_ACCELEROMETER);
        sensorManager.registerListener(mySensorEventListener,sensor, SensorManager.SENSOR_DELAY_FASTEST);
    }
}
/**
 * 取消注册Sensor
 */
public void unRegisterSensor(){
    if (sensorManager!=null) {
        Sensor sensor = sensorManager.getDefaultSensor( Sensor.TYPE_ACCELEROMETER);
        sensorManager.unregisterListener(mySensorEventListener,sensor);
    }
}
摇晃手机,加速度获取
package cn.zengfansheng.lottery.view.listener;
 
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.os.Vibrator;
 
/**
* 处理手机摇晃监听
*
* @author hacket
*/

public abstract class ShakeListener implements SensorEventListener {
 
    private long lastSampleTime;// 上一次采样时间
    private float lastPointX;// 上一个点的x轴加速度信息
    private float lastPointY;// 上一个点的y轴的加速度信息
    private float lastPointZ;// 上一个点的z轴的加速度信息
 
    private final long DURATION = 100;// 采样的时间间隔
 
    private float onceShake;// 一次摇晃增量
    private float totalShake;// 总摇晃增量
 
    private final float SWITCHSHAKEVALUE = 180;// 判断是否摇晃手机的阈值
 
    private Context context;
 
    // note*********************构造方法和数据初始化*********************
 
    public ShakeListener(Context context) {
        this.context = context;
        init();
    }
    public void init() {
 
        lastSampleTime = 0;
        lastPointX = 0;
        lastPointY = 0;
        lastPointZ = 0;
 
        onceShake = 0;
        totalShake = 0;
    }
 
    // note*********************sensor获取的数据变化*********************
    @Override
    public void onSensorChanged(SensorEvent event) {
 
        // 如何判断是否在摇晃手机?
        // 1、获取摇晃轨迹上的点的加速度值(三个轴),定义采样的时间间隔(手机性能决定)
        // 2、获取第一个采样点数据,记录数据操作
        // 3、获取第二点数据,与上一个点记录的信息进行处理:获取三个轴的增量
        // 4、汇总增量值
        // 5、以此类推,获取之后的一系列点数据,进行增量汇总
        // 6、当汇总的增量大于某个阈值(测试),认为用户在摇晃手机
 
        if (lastSampleTime == 0) {// 上一次采样时间为0,就是第一次采样
            // 记住时间
            lastSampleTime = System.currentTimeMillis();
 
            // 获取第一次的x,y,z轴的信息
 
            lastPointX = event.values[0];
            lastPointY = event.values[1];
            lastPointZ = event.values[2];
        } else {// 如果不是第一次
 
            // 当前采样时间
            long currentSampTime = System.currentTimeMillis();
 
            // 如果两次采样时间间隔大于100ms
            if (currentSampTime - lastSampleTime >= DURATION) {
 
                // 第二个点;
                float x = event.values[0];
                float y = event.values[1];
                float z = event.values[2];
 
                // 两个点之差
                float dx = Math.abs(lastPointX - x);
                float dy = Math.abs(lastPointY - y);
                float dz = Math.abs(lastPointZ - z);
 
                // 每次传入的数据:存在微小的变动
                // 防止手机放在那,静止的时候,慢慢的随着时间,就是不定时的震动一次
                if (dx < 1) {
                    dx = 0;
                }
                if (dy < 1) {
                    dy = 0;
                }
                if (dz < 1) {
                    dz = 0;
                }
 
                // 单次摇晃增量
                onceShake = dx+dy+dz;
 
                if (onceShake == 0) {
                    // 处于静止状态
                    init();
                }
 
                // 总的摇晃增量
                totalShake += onceShake;
 
                // 判断是否大于阈值了
                if (totalShake > SWITCHSHAKEVALUE) {
 
                    // 机选一注彩票:当前Listener在处理震动的判断,生成一注彩票工作不宜在此处理
                    // 由于有多种彩票,所以不应该在这个写死,而应该暴露出去一个方法,让需要的彩种自己去实现
                    createLottery();
 
                    // 提醒用户:声音或者震动
                    vibrate();
 
                    // FIXME 恢复初值,防止以后不停的震动
                    init();
 
                } else {// 继续获取
                    // 记住时间
                    lastSampleTime = System.currentTimeMillis();
 
                    lastPointX = event.values[0];
                    lastPointY = event.values[1];
                    lastPointZ = event.values[2];
                }
 
            }
        }
    }
 
    /**
     * 震动手机
     */

    private void vibrate(){
        // 获取震动器
        Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
        // 震动手机,200ms
        vibrator.vibrate(250);
    }
 
    /**
     * 创建一注彩票
     */

    public abstract void createLottery();
 
    // note*********************和精度处理有关的 *********************
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }
}
问题1:不停的在获取球,不停的震动
解决:在获取一注完毕后,要记得清零
问题2:返回键,还在获取数据,不停的震动
在onPause()方法中,取消注册