VibrationEffect-这酥麻,不敢相信!

VibrationEffect-这酥麻,不敢相信!

本文章部分翻译自Android开发文档

本文章所用的封装工具类来自Sutils,欢迎Star或者使用

1. 前言

最近封装一个Android震动工具类,在封装时候发现Api26出现了新的方法,然后就翻看Android开发文档,发现还有点意思,同时借着写API的缘故就写了这篇文章,在写文章之前,我测试了一下我写的工具类,点击开始震动,把手机握在手里的时候,我都产生了大胆的想法了……

请自动忽略标题。

2. 旧版API

1
2
3
4
5
6
7
8
9
10
11
/**
* 设置震动
* @param context 上下文
* @param milliseconds 震动时长
* */
@SuppressLint("MissingPermission")
public static void startVibrate(Context context, long milliseconds){
check(context);
vibrator = (Vibrator)context.getSystemService(VIBRATOR_SERVICE);
vibrator.vibrate(milliseconds);
}

上面这个方法,我们可能会经常用到,学习震动的时候也见到过,核心代码两行。传入震动时长即可震动,注意单位是ms

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 开始震动
* @param context 上下文
* @param pattern 震动规则
* 例如{100,200,300,400}表示震动100ms
* 等待200ms,震动300ms,等待400ms,循环
* 规则见repeat参数
* @param repeat 重复 传入0就是从开头一直重复下去,
* 传入-1就是不重复震动。
* 传入其他数字,就是从index下标开始重复
* */
@SuppressLint("MissingPermission")
public static void startVibrate(Context context, long[] pattern, int repeat){
check(context);
vibrator = (Vibrator)context.getSystemService(VIBRATOR_SERVICE);
vibrator.vibrate(pattern,repeat);
}

这个方法更高级一些,我们会传入一个long数组,一个int的值,其中long数组是震动规则,在上面的javadoc里面都写的很详细了,我们写一个最短的规则,让它一直循环就可以达到震震停停的效果,其中repeat参数就是控制重复循环的,其中0就是正常循环(从头一遍一遍的),-1就是不循环,而如果传入2,就是第二次从pattern[2]开始循环。

假如我们循环了,如何让他们停下来?

1
2
3
4
5
6
7
8
/**
* 停止震动
* */
@SuppressLint("MissingPermission")
public static void stopVibrate(){
if(vibrator != null)
vibrator.cancel();
}

就是调用cancel方法即可。

同时我们最重要的两个部分,一是要有振动器这个硬件,另一个是获取了震动权限。

1
2
3
4
5
6
7
8
9
10
/**
* 是否有震动器
* @param context 上下文
* @return true有 false没有
* */
public static boolean hasVibrator(Context context){
check(context);
vibrator = (Vibrator)context.getSystemService(VIBRATOR_SERVICE);
return vibrator.hasVibrator();
}
1
<uses-permission android:name="android.permission.VIBRATE" />

上面是一些旧版的API,目前已经标识过时了,取而代之的就是我们下面要说的内容,这是API26加入的新内容。

3.VibrationEffect

这玩意还挺新奇,我查了一下API,决定挑重点翻译一下,鉴于我我蹩脚的英语水平,特地请来Google翻译来帮忙,请见谅……下列引用内容原版来自Android Sdk doc 和 Android Developer,其他内容为自行补充。

VibrationEffect是一个抽象类,官方给他的解释如下:

VibrationEffect描述了由振动器执行的触觉效果。 这些效果可能是任何数量的因素,从单一振动到复杂波形。

有了它,我们就可以实现单一振动(也就是传入时长),复杂振动(也就是波形)。

我们来看看它的几个方法。

1
public static VibrationEffect createOneShot(long milliseconds,int amplitude)

功能:创造一次性振动。 一次振动将以指定的振幅在指定的时间段内持续振动,然后停止。

milliseconds:振动的毫秒数。 这必须是一个正数。

amplitude:振动的强度。 它必须是1到255之间的值,或DEFAULT_AMPLITUDE。

我们可以看到这个方法,是创建单一震动的,传入的第二个参数,是我们之前的API所没遇到过的,是0-255标识的振动强度,同时我们可以传入标准振动的常量值【DEFAULT_AMPLITUDE】

我们在Sdk中可以看到这个值是-1。

1549705545873

其实可以看出,官方为了写强度范围判断还费了好大力气,不清楚他们为什么要弄这么个默认值,具体这个-1代表多大的强度,我也不去考究了。

下面是我工具类中封装的,经过刚才的分析,相信你已经可以理解了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* API26 普通震动
* @param context 上下文
* @param milliseconds 震动时长
* @param amplitude 振动强度,1到255之间的值,或者DEFAULT_AMPLITUDE
* */
@SuppressLint("MissingPermission")
public static void startVibrate(Context context, long milliseconds, int amplitude){
check(context);
vibrator = (Vibrator)context.getSystemService(VIBRATOR_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
vibrator.vibrate(VibrationEffect.createOneShot(milliseconds,amplitude));
}
}

下面是另一个方法。

1
2
3
public static VibrationEffect createWaveform (long[] timings,
int[] amplitudes,
int repeat)

功能:创建波形振动。 波形振动是可能重复的一系列定时和幅度对。 对于每对,振幅数组中的值确定振动的强度,并且时序数组中的值确定振动的时间长度。 幅度为0意味着没有振动(即关闭),并且将忽略具有定时值0的任何对。要使模式重复,请将索引传递到开始重复的时序数组,或-1以禁用重复。

timings:定时/幅度对的定时值。 定时值为0将导致该对被忽略。

amplitudes:定时/幅度对的幅度值。 幅度值必须介于0到255之间,或等于DEFAULT_AMPLITUDE。 幅度值为0意味着关闭。

repeat:要重复的时序数组的索引,如果你不想重复,则返回-1。

可以看到createWaveform可以通过时长和振幅和重复来规定振动模式。

timings也即是旧API中的pattern数组,不需要再重复,只不过上面没提到,如果传入了0,将被忽略。

amplitudes是振幅值数组,同样我们要遵守数据规定。

repeat也是之前提过,可以通过传入0来实现普通重复,传入数组下标来实现高级重复,传入-1停止重复。

这样你就可以创作一个很舒服的振动效果……到底有多舒服,我也没试过……自行实践吧。

这个方法还有一个重载,省去了amplitudes,他默认的amplitudes是0和DEFAULT_AMPLITUDE的交替

1
public static VibrationEffect createWaveform (long[] timings, int repeat)

我们可以看到它的实现

1549714911579

下面是我的封装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* API26 波形震动
* @param context 上下文
* @param timings 交替开关定时的模式,从关闭开始。0的定时值将导致定时/振幅对被忽略。
* @param amplitudes 振幅值中的振幅值。振幅值必须为0和255之间,或为DEFAULT_AMPLITUDE。振幅值为0意味着断开。
* @param repeat 振动重复的模式,如果您不想重复,则将索引放入计时数组中重复,或者-1。
* */
@SuppressLint("MissingPermission")
public static void startVibrateWave(Context context, long[] timings, int[] amplitudes, int repeat){
check(context);
vibrator = (Vibrator)context.getSystemService(VIBRATOR_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
vibrator.vibrate(VibrationEffect.createWaveform(timings,amplitudes,repeat));
}
}

上面就是VibrationEffect类的三个对外方法,还有一个负责序列化的方法就不提了。

4. 总结

本文章一方面是探讨一下新版的API,另一方面是为Sutils-Vibrates做详细文档。

这里再总结一下Sutils-Vibrates的使用原则。

  • 使用时请注意配置context全局初始化
  • 注意添加震动权限
  • 在特殊的设备上注意振动的是否有判断器
  • 启动循环振动之后,要使用stopVibrate停止震动