安卓系统中实现摇一摇画面振动效果的方法
前言
在微信刚流行的时候,在摇一摇还能用来那啥的时候,我也曾深更半夜的拿着手机晃一晃。当时想的最多的就是,我靠,为神马摇一下需要用这么大的力度,当时我想可能腾讯觉得那是个人性的设计,后来才发觉尼马重力加速度设得太高了吧。扯多了,最近项目里需要解决一个振动的问题,因此在学习振动实现的过程中,写了个demo实现了摇一摇振动的效果,这里记录一下。
原理
摇一摇功能的基本原理就是:利用手机的加速度传感器,当加速度到达某个值时,触发某个事件,例如手机振动、UI改变等。这里要实现该功能,首先需要了解一下Android传感器的使用。
Android传感器Sensor使用
Android中有多种传感器,目前AndroidSDK支持的传感器包括:加速度传感器、光线传感器、陀螺仪传感器、重力传感器、方向传感器、磁场传感器、压力传感器等。但是并不是所有手机都具有这些传感器的,因为传感器需要money,因此廉价的手机会选择常用的传感器来添加,而且一些高端机型则基本上具有大多数传感器。
Sensor使用步骤
Android传感器的使用步骤大致可分为三步:
1.获取传感器管理服对象SensorManager。
2.创建传感器事件监听类,该类必须实现android.hardware.SensorEventListener接口。
3.使用SensorManager.registerListener方法注册指定的传感器。
传感器事件接口
SensorEventListener接口,该接口的onSensorChanged()和onAccuracyChanged()方法用于处理相应的传感器事件。
publicinterfaceSensorEventListener{
/**
*Calledwhensensorvalueshavechanged.
*<p>See{@linkandroid.hardware.SensorManagerSensorManager}
*fordetailsonpossiblesensortypes.
*<p>Seealso{@linkandroid.hardware.SensorEventSensorEvent}.
*
*<p><b>NOTE:</b>Theapplicationdoesn'townthe
*{@linkandroid.hardware.SensorEventevent}
*objectpassedasaparameterandthereforecannotholdontoit.
*Theobjectmaybepartofaninternalpoolandmaybereusedby
*theframework.
*
*@parameventthe{@linkandroid.hardware.SensorEventSensorEvent}.
*/
publicvoidonSensorChanged(SensorEventevent);
/**
*Calledwhentheaccuracyofasensorhaschanged.
*<p>See{@linkandroid.hardware.SensorManagerSensorManager}
*fordetails.
*
*@paramaccuracyThenewaccuracyofthissensor
*/
publicvoidonAccuracyChanged(Sensorsensor,intaccuracy);
}
Android振动实现
Android振动效果实现主要是依靠Vibrator服务,具体调用方法如下代码所示:
importandroid.app.Activity;
importandroid.app.Service;
importandroid.os.Vibrator;
publicclassVibratorHelper{
publicstaticvoidVibrate(finalActivityactivity,longmilliseconds){
Vibratorvibrator=(Vibrator)activity
.getSystemService(Service.VIBRATOR_SERVICE);
vibrator.vibrate(milliseconds);
}
publicstaticvoidVibrate(finalActivityactivity,long[]pattern,
booleanisRepeat){
Vibratorvibrator=(Vibrator)activity
.getSystemService(Service.VIBRATOR_SERVICE);
vibrator.vibrate(pattern,isRepeat?1:-1);
}
}
同时,还需要在AndroidManifest.xml里增加振动权限:
<uses-permissionandroid:name="android.permission.VIBRATE"/>
解释一下Vibrate方法的参数:
1.longmilliseconds:振动的时长,单位是毫秒。
2.long[]pattern:自定义振动模式。数组中数字的含义依次是[静止时长,振动时长,静止时长,振动时长,......]。振动时长的单位是毫秒。
3.repeat:是否重复振动,1为重复,-1为只振动一次。
摇一摇振动Demo实现
好了,了解了摇一摇需要借助加速度传感器,振动需要借助Vibrator服务,那就直接来写代码了。MainActivity类实现如下:
importandroid.app.Activity;
importandroid.app.AlertDialog;
importandroid.content.Context;
importandroid.content.DialogInterface;
importandroid.content.DialogInterface.OnClickListener;
importandroid.hardware.Sensor;
importandroid.hardware.SensorEvent;
importandroid.hardware.SensorEventListener;
importandroid.hardware.SensorManager;
importandroid.os.Bundle;
importandroid.util.Log;
importandroid.widget.Toast;
publicclassMainActivityextendsActivity{
privateSensorManagersensorManager;
privateSensorEventListenershakeListener;
privateAlertDialog.BuilderdialogBuilder;
privatebooleanisRefresh=false;
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sensorManager=(SensorManager)getSystemService(Context.SENSOR_SERVICE);
shakeListener=newShakeSensorListener();
dialogBuilder=newAlertDialog.Builder(this);
dialogBuilder.setPositiveButton("确定",newOnClickListener(){
@Override
publicvoidonClick(DialogInterfacedialog,intwhich){
isRefresh=false;
dialog.cancel();
}
}).setMessage("摇到了一个漂亮妹子!").create();
}
@Override
protectedvoidonResume(){
sensorManager.registerListener(shakeListener,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_FASTEST);
super.onResume();
}
@Override
protectedvoidonPause(){
//acitivity后台时取消监听
sensorManager.unregisterListener(shakeListener);
super.onPause();
}
privateclassShakeSensorListenerimplementsSensorEventListener{
privatestaticfinalintACCELERATE_VALUE=20;
@Override
publicvoidonSensorChanged(SensorEventevent){
//Log.e("zhengyi.wzy","typeis:"+event.sensor.getType());
//判断是否处于刷新状态(例如微信中的查找附近人)
if(isRefresh){
return;
}
float[]values=event.values;
/**
*一般在这三个方向的重力加速度达到20就达到了摇晃手机的状态x:x轴方向的重力加速度,向右为正y:
*y轴方向的重力加速度,向前为正z:z轴方向的重力加速度,向上为正
*/
floatx=Math.abs(values[0]);
floaty=Math.abs(values[1]);
floatz=Math.abs(values[2]);
Log.e("zhengyi.wzy","xis:"+x+"yis:"+y+"zis:"+z);
if(x>=ACCELERATE_VALUE||y>=ACCELERATE_VALUE
||z>=ACCELERATE_VALUE){
Toast.makeText(
MainActivity.this,
"acceleratespeed:"
+(x>=ACCELERATE_VALUE?x
:y>=ACCELERATE_VALUE?y:z),
Toast.LENGTH_SHORT).show();
VibratorHelper.Vibrate(MainActivity.this,300);
isRefresh=true;
dialogBuilder.show();
}
}
@Override
publicvoidonAccuracyChanged(Sensorsensor,intaccuracy){
//TODOAuto-generatedmethodstub
}
}
}
效果图: