Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to keep the vibrator on indefinitely from a service or receiver

I need to alert the user of certain events by means of:

  • Vibration
  • Notification

The vibration should remain on indefinitely until the user ACKs the notification.

The problem is vibration stops when the device goes to sleep. I've read the following questions:
Allow phone to vibrate when screen turns off
Continue vibration even after the screen goes to sleep mode in Android

There was an answer to one of the above mentioned questions saying that vibrating without patterns did the trick. So I've tried calling the version of Vibrator.vibrate that accepts milliseconds instead of a pattern with a large number but the vibration stops anyway.

Other answers suggest to register a receiver on the ACTION_SCREEN_OFF action. This would allow me to resume vibration if the device goes to sleep after the alarm has started, but won't work if the device was already slept.

However, I could get the thing working if I were able to turn the screen on first, then register the receiver to deal with any screen off event that could happen from there on. So I've tried acquiring a full wake lock when the triggering event is received, before starting sound or vibration, but it does not work despite I'm using the flags FULL_WAKE_LOCK and ACQUIRE_CAUSES_WAKEUP. The wakeup part works, but soon after that the device goes to sleep again. I would like to think the FULL_WAKE_LOCK flag does not work because it has been deprecated in API 17, but my device is a Samsung running 4.1.2 which is API 16!

The recommended approach now seems to be using WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON but this should be called from an activity, and I don't have any screen up unless the user clicks in the notification, and if this happens the sound and vibration should already have been stopped.

So it looks like a dead-end.

What else could I try?

UPDATE:
I had no luck keeping the screen always on with wake locks, but on the other hand they allow me to turn the screen on if only for a few seconds. I actually don't need to keep the screen on, so I'm registering the receiver on the Intent.ACTION_SCREEN_OFF action, and when the screen goes off, the receiver resumes vibration again. This worked well in the Samsung, but I've now switched to a Huawei to continue testing and the receiver does not work.

UPDATE:
Here's the stack trace of the exception in the Huawei device:

    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)
like image 585
Mister Smith Avatar asked Jun 11 '14 09:06

Mister Smith


1 Answers

Do you intend to let the device go to sleep or not? You can acquire a wakelock that wakes the screen on.

    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);

That doesn't work for you? After that you can show the notification, but I'm not sure of the effect, will it hold the vibrations. Above one works on GalaxyTab 2 with android 4.2.2 and HTC Hero with android 2.3.4.

like image 176
Nexowski Avatar answered Sep 27 '22 21:09

Nexowski