Application description:
The application is intended as a safety program for a specific client (not to be deployed publicly). When the application has not detected movement for a certain period of time, the application should sound an alarm and bring itself to the foreground if it is in the background or the device is asleep.
The problem:
In the event the device is asleep and locked, we need to wake up and unlock the device. Using various techniques found here on SO and other places, we've been able to (partially) wake and unlock the device, however this ONLY behaves properly when the device is physically plugged in to a computer. If the device is sitting by itself unplugged, and we test the wake-unlock, nothing happens; the device seems to remain asleep, and the application seems to do nothing at all (no alarm).
I have used this post about using PowerManager and KeyguardManager, and this post using window flags.
Here is the code presently used to wake the device:
public void wakeDevice() {
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock((PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "TAG");
wakeLock.acquire();
KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
KeyguardLock keyguardLock = keyguardManager.newKeyguardLock("TAG");
keyguardLock.disableKeyguard();
runOnUiThread(new Runnable(){
public void run(){
getWindow().addFlags(
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
}
});
}
From the comments and posts on some of the other SO questions I've seen / used, it seems as though the PowerManager / KeyguardManager code should have done the trick. Again, as I said before, it does technically work while the device is plugged in via USB to the dev machine, but does absolutely nothing while the device is separated.
Also note this is our first Android application, and so are fully aware we might be completely off on what we are trying to do. Any suggestions are welcome.
So in short, given the code above, why does the device behave so differently based on whether it is plugged in, and what should we change in order to wake and unlock the device as described? Thank you in advance for your assistance!
I solved the issue. The reason we observed different behaviour when the device was plugged in via USB was because the device's CPU was not going to sleep. I assume this is either a result of the debug mode setting, or simply how it behaves when plugged in to a computer since the power-saving feature of CPU-sleeping would be irrelevant. Obviously, when the device is not plugged in, the CPU would happily take a nap, and while we did observe the application randomly running (it would wake itself up at random times), the timing would be inconsistent. I further assume this is because the few CPU cycles that occurred are allocated sparingly, and our application would be given very few cycles at "random" times.
So our solution was to grab a partial wake lock when the device goes into the background (which is done in the onPause method), and release the lock in the onResume method. This seems to prevent the CPU from sleeping. We continue to use the full wake lock and keyguard disable to wake the device when we need to. Using the partial wake lock seems to keep the CPU from sleeping, and the device does appear to wake up properly when expected. Here is our updated code, in case anyone comes across this issue:
// Called from onCreate
protected void createWakeLocks(){
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
fullWakeLock = powerManager.newWakeLock((PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "Loneworker - FULL WAKE LOCK");
partialWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Loneworker - PARTIAL WAKE LOCK");
}
// Called implicitly when device is about to sleep or application is backgrounded
protected void onPause(){
super.onPause();
partialWakeLock.acquire();
}
// Called implicitly when device is about to wake up or foregrounded
protected void onResume(){
super.onResume();
if(fullWakeLock.isHeld()){
fullWakeLock.release();
}
if(partialWakeLock.isHeld()){
partialWakeLock.release();
}
}
// Called whenever we need to wake up the device
public void wakeDevice() {
fullWakeLock.acquire();
KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
KeyguardLock keyguardLock = keyguardManager.newKeyguardLock("TAG");
keyguardLock.disableKeyguard();
}
Related
I started songs on one of the music apps, on my android device.
Although I can see only partial wake_locks being acquired, still device display doesn't turn off even after screen timeout.
I wonder what is keeping the device screen on.
Can someone suggest where to look for probable cause.
Thanks!
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = pm.newWakeLock(
pm.SCREEN_DIM_WAKE_LOCK, "My wakelook");
// This will make the screen and power stay on
// This will release the wakelook after 1000 ms
wakeLock.acquire(1000);
// Alternative you can request and / or release the wakelook via:
// wakeLock.acquire(); wakeLock.release();
I used this code and works fine to me.
I am developing an application which should detect user movement and when he stops for more than 5 minutes it should sound an alarm. I was able to detect movement with accelerometer but the problem is it doesnt work when the screen is off. I have also tried using partial wakeLock. Re-registering accelerometer doesnt work either (this should be workaround for motorola devices).
Maybe I can do this using GPS and sound an alarm when GPS speed is less than 1m/s for more than 5 minutes but I am not sure if I will receive GPS updates when screen is off.
So I need a solution that will detect user movement even is screen is off on most devices. Any ideas on how to acomplish this?
Thanks in forward
You should acquire a partial wake lock for this kind of operation. Use the PowerManager class.
Something like this:
PowerManager pm = (PowerManager)getSystemService(POWER_SERVICE);
PowerManager.WakeLock lock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SensorRead");
lock.acquire();
You need also this permission in the AndroidManifest.xml:
<uses-permission android:name="android.permission.WAKE_LOCK" />
Is recommendable using lock.release(); when you're done your work.
EDIT:
Also, this article could be useful for you.
partial wake lock this is what you need to access while your screen is off.
private PowerManager.WakeLock mWakeLock;
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag");
mWakeLock.acquire();
And after you're done, just release the lock:
mWakeLock.release();
If you obtain accelerometer data in a Service, you could simply acquire lock in it's onCreate() and release in onDestroy().
I'm trying to make an App on Android 2.2 that has to run whether the screen is on or off.
I tried realizing it via a Service, but when my phone turns the screen off the service stopps working and I don't understand why.
In my Application I use
startService(new Intent(this, MyService.class));
when the User presses a button
and
Notification notification = new Notification();
startForeground(1, notification);
in the onCreate-Method of the Service class
(I tried it within the onStart() Method, too)
(I also could not find out what the id-field of startForeground() expects so I used the 1)
The service then should start an infinite vibration pattern of the phone so I know whether it is running or not.
But when I turn off the screen, the phone stops vibration immediately
Please help me. I don't know how I can fix that (and google was not a big help)
Sincerely
zed
Android devices go to a sleep mode when idle (e.g. when the screen is off), in order to conserve the battery.
To keep your service running you need to aquire a WakeLock. There are plenty of tutorials how to use it, like this one.
Note that having a service running all the time will drain your battery. Also make absolutely sure to release the wakelock when not needed, otherwise you're phone will always be awake.
Try returning 'START_STICKY' from 'onStartCommand() '. This will keep the service running, restarting it if necessary, without keeping the screen on.
Have a look at http://developer.android.com/reference/android/app/Service.html#START_STICKY
try this
KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
final KeyguardManager.KeyguardLock kl = km .newKeyguardLock("MyKeyguardLock");
kl.disableKeyguard();
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
WakeLock wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK
| PowerManager.ACQUIRE_CAUSES_WAKEUP
| PowerManager.ON_AFTER_RELEASE, "MyWakeLock");
wakeLock.acquire();
and in manifest file
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
so when your notification or alarm manager service running, screen will light on and the keyguard will unlock.I wish it works for who has this problem too.
I want to keep Wi-Fi enabled when device goes to sleep mode, I tried several options, but nothing has worked out like acquire Wi-Fi lock and set wi-fi enabled. These options are not working then I tried with wake lock, this is working perfectly when my application running in the foreground, but when application is running in background, after some time excess wake lock error comes and application is getting destroyed and on top of that I can't use wake lock all the time because it dried out the battery.actual requirement is my application should run 24/7 and connectivity with the server always stays on because server can send data any time, but when device goes to sleep mode wi-fi is getting turned off so I need to set the wi-fi sleep policy to never upon starting of my application and will set back to normal policy when application gets destroyed. I tried following code in my main activity and runs the application and allow device to go to sleep mode and after some time connection is still getting closed:
Settings.System.putInt(getContentResolver(),
Settings.System.WIFI_SLEEP_POLICY,
Settings.System.WIFI_SLEEP_POLICY_NEVER);
So please do help me to resolve this issue.
Use import static android.provider.Settings.System.WIFI_SLEEP_POLICY; instead of the name string Settings.System.WIFI_SLEEP_POLICY.
It works perfectly.
In my case Settings.System.WIFI_SLEEP_POLICY does not work. I was able to keep wi-fi on with the PowerManager
final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag");
wl.acquire();
Then in the OnDestroy() I call
wl.release();
Here's my scenario. I have an app that is playing backgound sounds. Using the BroadcastReceiver I can tell when the display turns off, and then kill the sounds. I can also tell if the screen turns back on. However, if the device is in the lock state I don't want the audio to start. Therefore I wait for the ACTION_USER_PRESENT intent to signal. That all works, except that if the user turns the screen back on quickly after it was turned off, you don't get the lock screen or the ACTION_USER_PRESENT message. So, is there a way to tell, when the screen turns back on, if the device is locked or not, which I guess also means sleeping or not?
((PowerManager) getSystemService(Context.POWER_SERVICE)).isScreenOn()
You can try the KeyguardManager to check if the device is locked. Here is some code (I haven't tried this myself):
KeyguardManager kgMgr = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
boolean showing = kgMgr.inKeyguardRestrictedInputMode();
Good luck!
Satur9nine's solution was right at the time, but since then isKeyguardRestricatedInputMode() was deprecated. Some powerManager related functionalities are now deprecated as well.
There's a newer, more accurate solution: isKeyguardLocked() for whether the device is locked, and a different approach to obtain whether the screen is interactive; You're looking for a combination of both.
KeyguardManager appKeyguard = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
PowerManager appPowerManager = (PowerManager) getSystemService(Context,POWER_SERVICE);
boolean showing = !appKeyguard.isKeyguardLocked() && appPowerManager.isInteractive();
((PowerManager) getSystemService(Context.POWER_SERVICE)).isScreenOn()
tells if the screen is on. So, it gets true if the screen is on but the device is locked.
Instead,
inKeyguardRestrictedInputMode()
gets true just if the device is locked.