【问题标题】:How to keep the vibrator on indefinitely from a service or receiver如何通过服务或接收器无限期地保持振动器开启
【发布时间】:2014-06-11 09:29:19
【问题描述】:

我需要通过以下方式提醒用户某些事件:

  • 振动
  • 通知

在用户确认通知之前,振动应无限期保持。

问题是设备进入睡眠状态时振动停止。我已阅读以下问题:
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)

【问题讨论】:

    标签: java android wakelock android-vibration


    【解决方案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。

    【讨论】:

    • 这些实际上是我的标志,除了ON_AFTER_RELEASE,我不需要。而三星的情况是它实际上是打开的,但在 1 或 2 秒后它又熄灭了,而我没有释放锁。现在没关系,因为我实际上并不需要一直打开屏幕。我会发布一个答案来解释我做了什么。
    • 太好了,感谢您的发布。
    【解决方案2】:

    经过一些测试,我终于设法让它工作了。

    Vibrator 类有两种方法:

    • vibrate (long[] pattern, int repeat)
    • vibrate (long milliseconds)

    first one 是使用 API 无限期振动的唯一方法(将 0 作为第二个参数传递)。但正如我在问题中发布的那样,这已被证明会破坏某些设备(华为)。我不是在谈论当设备进入睡眠状态时操作系统停止振动,这是使用接收器和问题中描述的唤醒锁来处理的。我说的是由错误的实现引起的异常(Vibrator 类是抽象的)。

    这个方法的second variant不接受模式,也不允许无限振动,但是我们可以通过传递一个非常大的毫秒数作为参数来作弊。正如the answer I cited in the question 正确指出的那样,这在某些设备(华为)中运行良好,但在其他设备(三星)中不起作用,其中实现具有默认的最大值,如果作为参数传递的值超过它,则将使用该最大值。这个最大值实际上不到一分钟,这意味着我们不能依赖这种方法。

    所以我全力以赴并创建了一个服务,我在其中手动无限期地振动,如下所示:

        while(vibrationActive){
            Vibrator.vibrate(1000); 
            Thread.sleep(1000);
        }
    

    不再需要检测屏幕何时熄灭的接收器技巧。当然,当这种情况发生时,操作系统会继续关闭振动器,但循环的下一次迭代将再次恢复振动。使用这种方法,如果睡眠时间大于振动时间,也可以创建一种模式,但是如果屏幕关闭,这种模式也会在任何时候中断。

    一项专门的服务,只是为了可靠地打开和关闭振动器。你相信吗?大约 150 行代码(没有单元测试),原本应该只需要几行代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多