BroadcastReceiver, Service and Wakelock - android

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

Related

How to wake up Android Wear when it is in sleep mode?

When Android Wear goes to sleep mode (screen dimmed), some parts of my code are not executed. I use Timer in background service to trigger some actions, such as sending data from wear to mobile, but the data is not sent. It is sent when I tap the screen to wake it up.
I also try to use Timer trigger a notification with vibration when the screen is off, but it doesn't appear until I tap the screen.
In debug mode (either Bluetooth or USB), data sending and notification work fine.
I suspect this is because when Android Wear is in sleep mode, its CPU works at minimum level because the Timer is still running, but not for GoogleApiClient, IntentService, or Notification.
I have tried many ways to wake CPU up such as AlarmManager, PowerManager, Wakelock, but it did not work for Android Wear.
Anyone has encountered this problem? What is the solution?
I'm using PowerManger to wakeup my wearable device each time i receive message from handled device.
Do not forget to release PowerManager.WakeLock
public abstract class WatchFaceActivity extends Activity {
private PowerManager.WakeLock mWakeLock;
private Handler mWakeLockHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_clock_watch_face);
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
mWakeLock = powerManager.newWakeLock((PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "MyWakelockTag");
mWakeLockHandler = new Handler();
IntentFilter messageFilter = new IntentFilter("message-forwarded-from-data-layer");
MessageReceiver messageReceiver = new MessageReceiver();
LocalBroadcastManager.getInstance(this).registerReceiver(messageReceiver, messageFilter);
}
public class MessageReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (!mWakeLock.isHeld()) {
mWakeLock.acquire();
}
mWakeLockHandler.removeCallbacksAndMessages(null);
mWakeLockHandler.postDelayed(mReleaseRunnable, 5000);
}
}
private Runnable mReleaseRunnable = new Runnable() {
#Override
public void run() {
mWakeLock.release();
}
};
#Override
protected void onDestroy() {
super.onDestroy();
mWakeLockHandler.removeCallbacksAndMessages(null);
mWakeLock.release();
}
}
And allow WAKE_UP permission in your Manifest.
<uses-permission android:name="android.permission.WAKE_LOCK" />
You should use AlarmManager along with WakefulBroadcastReceiver and startWakefulService(). See this working solution.
You may find answers for your further questions in chat history on that post here.This is the only solution worked for our app.
#SeaDog is successful in making http calls when device in deep sleep mode with this solution. Try it.

My app drains battery even that I release wake lock

I'm building a simple app that has BroadcastReciever that listens to PHONE_STATE:
<receiver android:name=".PhoneStateBroadcastReceiver" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
In the BroadcastReciever's onRecieve() I start a service when the state is OFFHOOK and stop the service when the state is IDLE:
public class PhoneStateBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
String state = bundle.getString(TelephonyManager.EXTRA_STATE);
if(state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
context.startService(new Intent(context, ProximityService.class));
}
else if(state.equals(TelephonyManager.EXTRA_STATE_IDLE)){
context.stopService(new Intent(context, ProximityService.class));
}
}
}
In the service I'm registering proximity sensor listener, and creating a WakeLock so the screen will turn off well while on call.
After the call ends I stop the service, and in its onDestroy() I'm unregistering the listener and release the WakeLock.
But it seems that something is not releasing out there because I see a huge battery drain from my app (30%).
I put a Log when the listener unregistering and also on the WakeLock release, and I can see that the WakeLock is released and the listener is unregistered successfully (I can also see the Log from SensorManager that the listener is unregistered).
What am I missing here?
That's really annoying.
Some code of the service:
public int onStartCommand(Intent intent, int flags, int startId){
Log.d("CALL", "Service started");
// Get an instance of the sensor service, and use that to get an instance of
// a particular sensor.
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mProximity = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
mSensorManager.registerListener(this, mProximity, SensorManager.SENSOR_DELAY_NORMAL);
mAudioManager = (AudioManager)this.getSystemService(Context.AUDIO_SERVICE);
mPowerMngr = (PowerManager) getSystemService(Context.POWER_SERVICE);
try{
mWakeLock = mPowerMngr.newWakeLock(PROXIMITY_SCREEN_OFF_WAKE_LOCK, "Proximity");
if (!mWakeLock.isHeld()) {
Log.d("CALL", "Wake lock acquired");
mWakeLock.acquire();
}
}
catch (Exception e){
mWakeLock = null;
}
return START_STICKY;
}
public void onDestroy(){
super.onDestroy();
mSensorManager.unregisterListener(this);
if (mWakeLock != null) {
if (mWakeLock.isHeld()) {
Log.d("CALL", "Wake lock released");
mWakeLock.release();
}
}
Log.d("CALL", "Service stopped");
}
The log I see:
09-30 03:35:09.120: D/SensorManager(21565): unregisterListener:: disable all sensors for this listener, listener = com.eladaharon.android.proximity.ProximityService#41a31a18
09-30 03:35:09.125: D/CALL(21565): Wake lock released
09-30 03:35:09.125: D/CALL(21565): Service stopped
Thanks a lot!
Elad
If your service is receiving multiple intents, your code will create a new WakeLock each time onStartCommand is executed. You would be releasing only the last WakeLock and leaking the others, which would explain the battery drain. Logcat will normally provide helpful messages in this situation.
Since your service remains running for a time, you could check whether mWakeLock is initialized before calling newWakeLock().

wifi connection is getting closed when device is going in sleep/locked state [duplicate]

I have a service which polls a server at certain intervals. I use an AlarmManager and a BroadcastReceiver to start the service. My problem is that after a certain duration, even though the Wifi is still enabled, but for some reason, my application can't contact the server. I get an "Unreachable network" error.
Note that I've already acquired a partial wake lock as well as a wifilock.
Here's my code for the BroadcastReceiver.
public class ServiceAlarmBroadcastReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
WakeLock wakeLock = null;
WifiLock wifiLock = null;
try {
PowerManager pm = (PowerManager) context
.getSystemService(Context.POWER_SERVICE);
// acquire a WakeLock to keep the CPU running
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MyWakeLock");
if(!wakeLock.isHeld()){
wakeLock.acquire();
}
Log.i("ServiceAlarmBroadcastReceiver", "WakeLock acquired!");
WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
wifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL , "MyWifiLock");
if(!wifiLock.isHeld()){
wifiLock.acquire();
}
Log.i("ServiceAlarmBroadcastReceiver", "WifiLock acquired!");
context.startService(new Intent(context, ThePollerService.class));
} finally {
// release the WakeLock to allow CPU to sleep
if (wakeLock != null) {
if (wakeLock.isHeld()) {
wakeLock.release();
Log.i("ServiceAlarmBroadcastReceiver", "WakeLock released!");
}
}
// release the WifiLock
if (wifiLock != null) {
if (wifiLock.isHeld()) {
wifiLock.release();
Log.i("ServiceAlarmBroadcastReceiver", "WiFi Lock released!");
}
}
}
}
}
The problem with the code posted here is that you acquire and release the WakeLock and WifiLock from right inside of your receiver. Unless you are completing your entire task inside of the onStart of your service (which if you are, why even bother having a service???), the locks will be released before your polling task completes.
I would suggest changing your implementation to something like the following:
Have broadcast receiver start service (and that is all)
Have service acquire wake locks and kick off the thread to do your polling operation. The most appropriate spot would be your service onCreate)
After your polled operation is complete, you should stop your polling service
In the onDestroy of your service, you should release the locks you acquired in onStart
Thanks to Tom, I was able to resolve this issue. Here's the code:
Settings.System.putInt(getContentResolver(),
Settings.System.WIFI_SLEEP_POLICY,
Settings.System.WIFI_SLEEP_POLICY_NEVER);
Under the WiFi Settings, Menu Key, Advanced Options theirs the WIFI_SLEEP_POLICY option list which when set to never will keep the WiFi connection open while the phone is asleep.
You can manipulate this under Settings.System Package.
http://developer.android.com/reference/android/provider/Settings.System.html#WIFI_SLEEP_POLICY
Hope this helps,
Tom
A little edit to javauser's answer:
private void setNeverSleepPolicy() {
try {
ContentResolver cr = getContentResolver();
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
int set = android.provider.Settings.System.WIFI_SLEEP_POLICY_NEVER;
android.provider.Settings.System.putInt(cr, android.provider.Settings.System.WIFI_SLEEP_POLICY, set);
} else {
int set = android.provider.Settings.Global.WIFI_SLEEP_POLICY_NEVER;
android.provider.Settings.System.putInt(cr, android.provider.Settings.Global.WIFI_SLEEP_POLICY, set);
}
} catch (Exception e) {
e.printStackTrace();
}
}

Android: Wake & unlock phone

I am trying to figure out how to wake and unlock the phone with a service. I have been referring to this post but, I can't figure out why it isn't working. This is the code that I have so far:
public class WakephoneActivity extends Activity {
BroadcastReceiver mReceiver;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Log.v(TAG, "Screen OFF onReceive()");
screenOFFHandler.sendEmptyMessageDelayed(0, 2000);
}
};
}
private Handler screenOFFHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
// do something
// wake up phone
// Log.i(TAG, "ake up the phone and disable keyguard");
PowerManager powerManager = (PowerManager) WakephoneActivity.this
.getSystemService(Context.POWER_SERVICE);
long l = SystemClock.uptimeMillis();
powerManager.userActivity(l, false);// false will bring the screen
// back as bright as it was, true - will dim it
}
};
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
registerReceiver(mReceiver, filter);
// Log.i(TAG, "broadcast receiver registered!");
}
}
I have added the code in the manifest as well. Any ideas?
Use this code below in your service.
PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock((PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "YourServie");
mWakeLock.acquire();
[...]
mWakeLock.release();
If you want to unlock the screen as well, register a receiver in your service that monitors if the screen is turned on/off and if it is turned off and you want to unlock the phone, start an activity with this code in onCreate:
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
this.finish();
return;
I know, this is a rather dirty, but as far as I know, there is no other way of unlocking the lockscreen (and this will only work if there are no passwords etc set, so it must be the normal "slide to unlock" screen).
And don't forget to add android.permission.WAKE_LOCK ;-)
/edit: I just saw you are already using an Activity. If you have one and don't need the service at all, just put this code into the activity.
For the service to be allways active you need to have this permission on manifest:
<uses-permission android:name="android.permission.WAKE_LOCK" />
Another thing you need to do is to adquire a WakeLock. Without it the service will end passed some time. You can do it like this:
getApplicationContext();
PowerManager pm = (PowerManager)getApplicationContext().getSystemService(Context.POWER_SERVICE);
WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
wl.acquire();
You might need to change PowerManager.PARTIAL_WAKE_LOCK to the one that you need. You can see info about that here.
There is WakefulBroadcastReceiver which does this for you. Example use:
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
import android.support.v4.content.WakefulBroadcastReceiver;
import android.util.Log;
public class SimpleWakefulReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// This is the Intent to deliver to our service.
Intent service = new Intent(context, SimpleWakefulService.class);
// Start the service, keeping the device awake while it is launching.
Log.i("SimpleWakefulReceiver", "Starting service # " + SystemClock.elapsedRealtime());
startWakefulService(context, service);
}
}
After completing the action in the service, call SimpleWakefulReceiver.completeWakefulIntent(intent) to release the wake lock.
(as #Force already gave you the details about the wakeLock, they need not be repeated here ;-)
Mind that the class is deprecated from api level 26.1.0, reference here

How do I keep Wifi from disconnecting when phone is asleep?

I have a service which polls a server at certain intervals. I use an AlarmManager and a BroadcastReceiver to start the service. My problem is that after a certain duration, even though the Wifi is still enabled, but for some reason, my application can't contact the server. I get an "Unreachable network" error.
Note that I've already acquired a partial wake lock as well as a wifilock.
Here's my code for the BroadcastReceiver.
public class ServiceAlarmBroadcastReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
WakeLock wakeLock = null;
WifiLock wifiLock = null;
try {
PowerManager pm = (PowerManager) context
.getSystemService(Context.POWER_SERVICE);
// acquire a WakeLock to keep the CPU running
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MyWakeLock");
if(!wakeLock.isHeld()){
wakeLock.acquire();
}
Log.i("ServiceAlarmBroadcastReceiver", "WakeLock acquired!");
WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
wifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL , "MyWifiLock");
if(!wifiLock.isHeld()){
wifiLock.acquire();
}
Log.i("ServiceAlarmBroadcastReceiver", "WifiLock acquired!");
context.startService(new Intent(context, ThePollerService.class));
} finally {
// release the WakeLock to allow CPU to sleep
if (wakeLock != null) {
if (wakeLock.isHeld()) {
wakeLock.release();
Log.i("ServiceAlarmBroadcastReceiver", "WakeLock released!");
}
}
// release the WifiLock
if (wifiLock != null) {
if (wifiLock.isHeld()) {
wifiLock.release();
Log.i("ServiceAlarmBroadcastReceiver", "WiFi Lock released!");
}
}
}
}
}
The problem with the code posted here is that you acquire and release the WakeLock and WifiLock from right inside of your receiver. Unless you are completing your entire task inside of the onStart of your service (which if you are, why even bother having a service???), the locks will be released before your polling task completes.
I would suggest changing your implementation to something like the following:
Have broadcast receiver start service (and that is all)
Have service acquire wake locks and kick off the thread to do your polling operation. The most appropriate spot would be your service onCreate)
After your polled operation is complete, you should stop your polling service
In the onDestroy of your service, you should release the locks you acquired in onStart
Thanks to Tom, I was able to resolve this issue. Here's the code:
Settings.System.putInt(getContentResolver(),
Settings.System.WIFI_SLEEP_POLICY,
Settings.System.WIFI_SLEEP_POLICY_NEVER);
Under the WiFi Settings, Menu Key, Advanced Options theirs the WIFI_SLEEP_POLICY option list which when set to never will keep the WiFi connection open while the phone is asleep.
You can manipulate this under Settings.System Package.
http://developer.android.com/reference/android/provider/Settings.System.html#WIFI_SLEEP_POLICY
Hope this helps,
Tom
A little edit to javauser's answer:
private void setNeverSleepPolicy() {
try {
ContentResolver cr = getContentResolver();
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
int set = android.provider.Settings.System.WIFI_SLEEP_POLICY_NEVER;
android.provider.Settings.System.putInt(cr, android.provider.Settings.System.WIFI_SLEEP_POLICY, set);
} else {
int set = android.provider.Settings.Global.WIFI_SLEEP_POLICY_NEVER;
android.provider.Settings.System.putInt(cr, android.provider.Settings.Global.WIFI_SLEEP_POLICY, set);
}
} catch (Exception e) {
e.printStackTrace();
}
}

Categories

Resources