我需要通过以下方式提醒用户某些事件:
振动应无限期保持不变,直到用户确认通知为止。
问题是当设备进入睡眠状态时振动停止。我已经阅读了以下问题:
Allow phone to vibrate when screen turns off
Continue vibration even after the screen goes to sleep mode in Android
上面提到的问题之一an answer说没有模式的振动就可以了。因此,我尝试调用Vibrator.vibrate
的版本,该版本接受毫秒而不是大数量的模式,但振动仍会停止。
其他答案建议在ACTION_SCREEN_OFF
行动中注册接收者。如果设备在闹钟开始后进入睡眠状态,这将允许我恢复振动,但如果设备已经睡眠则不能工作。
然而,如果我能够首先打开屏幕,然后注册接收器以处理可能从那里发生的任何屏幕关闭事件,我可以得到工作。所以我在接收到触发事件之前尝试获取完整的唤醒锁定,然后开始声音或振动,但是尽管我使用了标志FULL_WAKE_LOCK和ACQUIRE_CAUSES_WAKEUP,它仍无效。唤醒部分工作,但不久之后设备再次进入睡眠状态。我想FULL_WAKE_LOCK标志不起作用,因为它在API 17中已被弃用,但我的设备是运行4.1.2的三星,即API 16!
现在推荐的方法似乎是使用 WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON ,但应该从活动调用,除非用户点击通知,否则我没有任何屏幕,如果发生这种情况振动应该已经停止了。
所以它看起来像一个死胡同。
我还能尝试什么?
更新:
我没有运气保持屏幕始终打开唤醒锁,但另一方面,他们允许我打开屏幕,如果只有几秒钟。我实际上不需要保持屏幕开启,所以我在Intent.ACTION_SCREEN_OFF
动作上注册了接收器,当屏幕熄灭时,接收器再次恢复振动。这在三星上运行良好,但我现在转而使用华为继续测试,接收器不起作用。
更新:
这是华为设备中异常的堆栈跟踪:
java.util.NoSuchElementException: Death link does not exist
at android.os.BinderProxy.unlinkToDeath(Native Method)
at com.android.server.VibratorService.unlinkVibration(VibratorService.java:294)
at com.android.server.VibratorService.removeVibrationLocked(VibratorService.java:284)
at com.android.server.VibratorService.cancelVibrate(VibratorService.java:213)
at android.os.IVibratorService$Stub.onTransact(IVibratorService.java:83)
at android.os.Binder.execTransact(Binder.java:338)
at dalvik.system.NativeStart.run(Native Method)
答案 0 :(得分:1)
你打算让设备进入睡眠状态吗?你可以获得唤醒屏幕的唤醒锁。
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
WakeLock wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, "myTAG");
wl.acquire(LOCK_SCREEN_TIME_MINUTES * 60 * 1000);
那对你不起作用? 之后你可以显示通知,但我不确定效果,它会保持振动。上面的一个适用于带有android 4.2.2的GalaxyTab 2和带有android 2.3.4的HTC Hero。
答案 1 :(得分:1)
经过一些测试后,我终于成功了。
Vibrator课有两种方法:
vibrate (long[] pattern, int repeat)
vibrate (long milliseconds)
first one是使用API无限振动的唯一方法(将0作为第二个参数传递)。但正如我在问题中所发表的那样,已经证明这在某些设备(华为)中有所突破。我不是在讨论当设备进入睡眠状态时OS停止的振动,这已经使用接收器和问题中描述的唤醒锁来处理。我正在谈论由错误实现引起的异常(Vibrator类是抽象的)。
此方法的second variant不接受模式,并且不允许无限期振动,但我们可以通过传递非常大的毫秒作为参数来欺骗它。这在某些设备(华为)中运行良好,the answer I cited in the question正确指出,但在其他设备(三星)中不起作用,其他实现具有默认最大值,如果作为参数传递的值超过它,将使用该值。这个最大值实际上不到一分钟,这意味着我们不能依赖这种方法。
所以我全力以赴并创建了一个服务,我手动无限地振动:
while(vibrationActive){
Vibrator.vibrate(1000);
Thread.sleep(1000);
}
不再需要用于检测屏幕何时熄灭的接收器技巧。当然,操作系统会在发生这种情况时关闭振动器,但循环的下一次迭代将再次恢复振动。使用这种方法,如果睡眠时间大于振动时间,也可以创建一种模式,但如果屏幕熄灭,这个模式将在任何时候中断。
专门用于可靠地打开和关闭振动器的服务。你相信吗?大约150行代码(没有单元测试)可以用几行代码完成。