WakeLock not releasing and Screen isn't turning off - android

I've using alarm manager to call an activity and I'm using the wake locker class onRecive() to wake the phone and then calling WakeLocker.release() after the Activity is over but the screen still stays on...
Receive.class:
public class MyScheduledReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
WakeLocker.acquire(context);
Activity.class
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
WakeLocker.release();
finish();
}
I've put it in the onPause(), onStop() everywhere... the thing won't release and the screen won't turn off automatically after my app closes...

Make sure you request permission
<uses-permission android:name="android.permission.WAKE_LOCK" />

You are starting the wakelock in a broadcastreceiver and stopping it in an activity.
You are referencing 2 different instances of a wakelock. You should start the activity from the onreceive and in onresume acquire the wake lock, then still release in the onpause if that is where you want it to happen.
You should never start anything that is supposed to be around for awhile within a broadcastreceiver, because the receiver is destroyed as soon as possible.

Try this
PowerManager pm;
PowerManager.WakeLock wakeLock;
pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK,
"x2_wakelook");
wakeLock.acquire();
wakeLock.release();

Related

Correct pattern for BroadcastReceiver getting wakelock to start an Activity?

What's the right way to acquire a wakelock in a BroadcastReceiver, and hold it until an activity is started - this is what I have:
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
PowerManager pm = (PowerManager)
context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK,
"tag");
wl.acquire();
Intent intent = new Intent(context, MyActivity.class);
context.startActivity(intent);
}
}
public class MyActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PowerManager pm = (PowerManager)
context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK,
"tag");
wl.release();
// I want to keep the screen on now.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}
}
// The broadcastreceiver is fired via AlarmManager:
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, someTime, pendingIntent);
Additionally, what happens if the broadcast receiver gets fired simultaneously - I assume the wakelock manager is synchronized and this won't be a problem?
Thank you
Once a lock is acquired you have to keep this instance of lock and release exactly that instance once work is done. You can check source code of WakefulBroadcastReceiver.java to get better idea of how this can be implemented and used.
Additionally, it's not a very good idea to start activity from a broadcast receiver. Imagine you play a game and in the middle of a level your phone starts an activity. I don't think you will like it. You should rather post a notification that user can open activity later, when user wants it.

Check whether onPause state of activity is called due to screen lock

If my app is running and I press lock screen button, it will put the app in background.What is the method to check whether onPause() is called by screen lock?.Thanks in advance.
All you have to do is check if the screen is on or not.
#Override
protected void onPause() {
super.onPause();
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
boolean screenOn;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
screenOn = pm.isInteractive();
} else {
screenOn = pm.isScreenOn();
}
if (screenOn) {
// Screen is still on, so do your thing here
}
}
You Can Simply Know It By Using This Method
#Override
public void onPause() {
super.onPause(); // Always call the superclass method first
System.out.println("On Pause called");
}
For Keeping The Device Awake while lock screen. Documentation.
Ok in your case you would need Wake_Lock
To use a wake lock, the first step is to add the WAKE_LOCK permission to your application's manifest file:
<uses-permission android:name="android.permission.WAKE_LOCK" />
If your app includes a broadcast receiver that uses a service to do some work, you can manage your wake lock through a WakefulBroadcastReceiver, as described in Using a WakefulBroadcastReceiver. This is the preferred approach. If your app doesn't follow that pattern, here is how you set a wake lock directly:
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
Wakelock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MyWakelockTag");
wakeLock.acquire();
To release the wake lock, call wakelock.release(). This releases your claim to the CPU. It's important to release a wake lock as soon as your app is finished using it to avoid draining the battery.
DO this after setting powermanager.
boolean screenOn;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
screenOn = powerManager.isInteractive();
} else {
screenOn = powerManager.isScreenOn();
}
if (screenOn) {
// Screen is still on, so do your thing here
}
You just want to know when onPause is called? You could override the super function and add logging to the function:
#Override
public void onPause() {
super.onPause();
System.out.println("On Pause called");
}

Application is being killed while on background

My application sends gps updates to a API. I need my application to run in background all the time. But unfortunately, my application always end at some point while on background. I have read that when the cpu usage of the application is low, the application is will be killed automatically. I don't want this to happen. I already included a partial wake lock on my onCreate method in my application using this code:
powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLock");
Then on pause:
protected void onPause()
{
super.onPause();
onBackground = true;
wakeLock.acquire();
Log.w("OnPause", "OnPause");
}
I really don't know how to prevent my application being killed. I also tried using full wake lock but it is deprecated. Any ideas on how will I keep my application alive on background? I never want my application to be killed while on background. Thanks!
You can not.
Just make sure, you persist anything that should survive after being killed.
For anything that should run in background, even if the app is not shown to the user:
Use a Service and set it into foreground mode.
public class BGService extends Service {
private PowerManager powerManager;
private WakeLock wakeLock;
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MyWakeLock");
wakeLock.acquire();
}
call and start service in your main activity
public class SendSMSActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.demo);
startService(new Intent(this, BGService.class));
}
}

Android startActivity in BroadcastReceiver's onReceive function

I have the following code in my BroadcastReceiver's onReceive function.
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action == null) return;
if (action.equals(ACTION_ALARM)) {
Intent alarmPopup = new Intent(context, AlarmPopup.class);
int vibrateDuration = context.getSharedPreferences(PREF, 0)
.getInt(VIBRATE_DURATION, DEFAULT_VIBRATE_DURATION)
alarmPopup.putExtra(VIBRATE_DURATION, vibrateDuration);
alarmPopup.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(alarmPopup);
}
}
This code starts activity AlarmPopup as it receives alarm manager's broadcast.
Once the AlarmPopup activity is started, it shows a typical alarm message and vibrates during vibrateDuration passed through Intent#putExtra.
In AlarmPopup's onCreate method, the activity holds WakeLock to make the device keep turning on.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
wl = getLock(this);
if (!wl.isHeld()) {
Log.d(PREF, "Alarm popup acquires wake lock");
wl.acquire();
thread.run();
}
.
.
.
}
getLock is a synchronized method that manages WakeLock as WakefulIntentService does.
private static volatile PowerManager.WakeLock wlStatic = null;
synchronized private static PowerManager.WakeLock getLock(Context context) {
if (wlStatic == null) {
PowerManager mgr = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wlStatic = mgr.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK
| PowerManager.ACQUIRE_CAUSES_WAKEUP
| PowerManager.ON_AFTER_RELEASE, PREF);
wlStatic.setReferenceCounted(true);
}
return wlStatic;
}
Now here is the problem: even though context.startActivity(alarmPopup) is called, startActivity rarely does not start the activitiy or starts not on time, usually 1-2 minutes later.
It seems that OS kills my AlarmPopup activitiy in the middle of its creation or let the activity be created a little bit later than the time when startActivity was actually called.
What is really interesting is, when the above problem happens, sometimes the log message "Alarm popup acquires wake lock" is recorded and sometimes it is not even recorded. I think, in this case, OS kills the activity while it executes the first or second line of onCreate method.
How can I solve this problem?
Should I put some dummy code that holds the CPU at the end of onReceive while the AlarmPopup activity is being created by another thread?
It seems that OS kills my AlarmPopup activitiy in the middle of its creation or let the activity be created a little bit later than the time when startActivity was actually called.
No. The device simply fell asleep. startActivity() is an asynchronous operation. The WakeLock held by the OS for the AlarmManager work (assuming that you are, indeed, using AlarmManager) will be released when onReceive() returns. onCreate() of your activity will not have run by the time onReceive() returns. Hence, the device might fall asleep in the window of time between the end of onReceive() and when you acquire your WakeLock in onCreate().
How can I solve this problem?
Acquire the WakeLock in onReceive().

BroadcastReceiver, Service and Wakelock

im receiving an intent in broadcast receiver and then i start service to do more work. now what if the device is sleep and this happen, do i have to get Wakelock (AlarmManger?), and why do i need it?
does my service will stop running if the device goes to sleep without getting a wakelock.
now what if the device is sleep and this happen, do i have to get Wakelock (AlarmManger?), and why do i need it?
If the device is asleep to begin with, you will not be "receiving an intent in broadcast receiver", because the device is asleep.
do i have to get Wakelock (AlarmManger?), and why do i need it?
You don't "need it", unless you want to ensure the device stays running while you complete some work.
does my service will stop running if the device goes to sleep without getting a wakelock.
Yes.
Looks like the Android's native WakefulBroadcastReceiver would be a perfect solution for you. Need to extend this rather than the regular BroadcastReceiver and start the service in the onReceive() in the "wakeful" manner:
startWakefulService(context, service);
and signal your work is done in the service's onHandleIntent(), calling
MyWakefulReceiver.completeWakefulIntent(intent);
public class WakeLockManager extends BroadcastReceiver {
private static WakeLock mWakeLock;
private String LCLT;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Consts.WAKELOCK_INTENT)) {
Log.v("wakelock", "GOT THE wakelock INTENT");
boolean on = intent.getExtras().getBoolean("on");
if (mWakeLock == null) {
PowerManager pm = (PowerManager) context
.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"Breeze WakeLock");
}
if (on) {
if (!mWakeLock.isHeld()) {
mWakeLock.acquire();
Log.v("wakelock", "acquiring wakelock");
}
} else {
if (mWakeLock.isHeld()) {
Log.v("wakelock", "releasing wakelock");
mWakeLock.release();
}
mWakeLock = null;
}
}
}
}
look at the above code ..put it in a separate class file and and in your manifest define it for some custom intent .... now that this class will respond to a custom intent ...just broadcast that intent and you can turn the wakelock on or off in your entire app since the wakelock is static..like this :
public void setWakeup(boolean status) {
Intent wakelock_Intent = new Intent(CUSTOM_INTENT);
wakelock_Intent.putExtra("on", status);
this.sendBroadcast(wakelock_Intent);
}
the above would be defined in your alarmmanager code so it schedules a call

Categories

Resources