參考鏈接:
主體內容參考:http://blog.csdn.net/catoop/article/details/8051835
看到http://104zz.iteye.com/blog/1694738對應的文章時,想着應該把此功能做一個封裝
以下爲正文(實際上就是代碼)
項目地址:https://github.com/itlonewolf/Practice
使用參照項目中ShakeActivity中的示例
封裝後的搖一搖控制器(方便使用與複用)
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Vibrator;
import android.support.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.TimeUnit;
/**
* Created by xiaoyee on 16/7/28.
* 搖一搖控制器
* <p>
* 代碼主體參考http://blog.csdn.net/catoop/article/details/8051835
* 看到http://104zz.iteye.com/blog/1694738對應的文章時,想着應該把此功能做一個封裝
* </p>
*
*/
public class ShakeController implements SensorEventListener {
public interface Amplitude{
/**
* 對於過山車而言,得很大的搖動纔算事兒吧
*/
int ROLLER_COASTER = 100;
int SUV = 55;
int BIKE = 38;
/**
* 很小的搖動對於輪椅來講就是需要注意的了
*/
int WHEELCHAIR = 18;
}
/**
* 搖一搖兩次之間的間隔至少爲500ms
*/
private static final int SHAKE_TIME_SLOT = 500;
//不重複震動
private static final int DONT_REPEAT = -1;
//震動模式
private static final long[] VIBRATOR_PATTERN = new long[]{
//每兩個數值爲一個組合
100, 300,//100爲等待(停止)時間,300爲震動時間
200, 300 //200爲等待(停止)時間,300爲震動時間
};
private SensorManager mSensorManager;
private Vibrator mVibrator;
//是否需要震動,默認開啓震動
private boolean mNeedVibrate = true;
//上一次震動的時間戳;單位納秒
private long mLastTimeShake = 0;
//設當絕對值大於多少時纔算一次搖動
private int mShakeAmplitude = Amplitude.SUV;
private OnShakedListener mOnShakedListener;
/**
* 設置搖動幅度爲多少時,纔算是搖動
*/
public void setShakeAmplitude(@AmplitudeAnno int shakeAmplitude) {
mShakeAmplitude = shakeAmplitude;
}
/**
*
* @param needVibrate 是否需要開啓震動
*/
public ShakeController(Context context, boolean needVibrate) {
mNeedVibrate = needVibrate;
mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
}
/**
* 默認開啓震動
*/
public ShakeController(Context context) {
this(context, true);
}
public void startWatchShake(){
if (mSensorManager != null) {
mSensorManager.registerListener(
this,
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL
);
}
}
public void stopWatchShake(){
if (mSensorManager != null) {
mSensorManager.unregisterListener(this);
}
}
public void setOnShakedListener(OnShakedListener onShakedListener) {
mOnShakedListener = onShakedListener;
}
@Override
public void onSensorChanged(SensorEvent event) {
//驗證傳感器
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
float[] values = event.values;
float x = values[0]; // x軸方向的重力加速度,向右爲正
float y = values[1]; // y軸方向的重力加速度,向前爲正
float z = values[2]; // z軸方向的重力加速度,向上爲正
// 一般在這三個方向的重力加速度達到40就達到了搖晃手機的狀態。
if (Math.abs(x) > mShakeAmplitude || Math.abs(y) > mShakeAmplitude || Math.abs(z) > mShakeAmplitude) {
//使用此方法降低調用次數
if (isTimeSlot(event.timestamp)) {
if (mNeedVibrate) {
mVibrator.vibrate(VIBRATOR_PATTERN, DONT_REPEAT);
}
if (mOnShakedListener != null) {
mOnShakedListener.onShake();
}
}
}
}
}
/**
* 間隔時間是否大於要求值;目前間隔時間爲 {@link #SHAKE_TIME_SLOT 500ms}
* @param currentTime 本次時間;單位爲納秒
*/
private boolean isTimeSlot(long currentTime) {
if (TimeUnit.NANOSECONDS.toMillis(currentTime - mLastTimeShake) > SHAKE_TIME_SLOT) {
mLastTimeShake = currentTime;
return true;
}
return false;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
//暫時不關心此更改
}
/**
* 搖一搖監聽器
*/
public interface OnShakedListener{
void onShake();
}
@Retention(RetentionPolicy.SOURCE)
@IntDef({Amplitude.WHEELCHAIR, Amplitude.BIKE, Amplitude.SUV, Amplitude.ROLLER_COASTER})
private @interface AmplitudeAnno{}
}
使用示例:
public class ShakeActivity extends AppCompatActivity {
private ShakeController mShakeController;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_shake);
mShakeController = new ShakeController(this);
mShakeController.setOnShakedListener(new ShakeController.OnShakedListener() {
@Override
public void onShake() {
Toast.makeText(ShakeActivity.this, "搖一搖", Toast.LENGTH_SHORT).show();
}
});
}
@Override
protected void onResume() {
super.onResume();
mShakeController.startWatchShake();
}
@Override
protected void onPause() {
super.onPause();
mShakeController.stopWatchShake();
}
}