2

I am very confused whether to acquire this wakelock. E.g. I have this type of code that is called from onReceive() of a BroadcastReceiever (CONNECTIVITY_CHANGE, BOOT_COMPLETED etc) asynchronously i.e. I am launching an IntentService from onReceive() which performs heavy lifting.

private static void insertInDatabase(Context context /*, some data to be inserted in database*/) {
        Database helper = Database.getInstance(context);
        PowerManager pm = (PowerManager) context
            .getSystemService(Context.POWER_SERVICE);
        final WakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, wakelockName); 
        wakeLock.acquire();
        try { 
            SQLiteDatabase db = helper.getWritableDatabase();
            ContentValues cv = new ContentValues();
            // insert data in database here  
        } finally {
            wakeLock.release();
        }
    }

Is this scenario the right candidate to acquire PowerManager.PARTIAL_WAKE_LOCK?

M-Wajeeh
  • 17,204
  • 10
  • 66
  • 103

2 Answers2

3

The answer by @paha misses an important point : IntentService is not enough. Between onReceive() ends and the IntentService is started the phone might fall asleep again. You need a (static) lock to bridge this gap - this is implemented in Mark Murpphy's WakefulIntentService

So keep the AlarmManager and receiver but launch a WakefulIntentService from your onReceive().

See:

Community
  • 1
  • 1
Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
  • Exactly, that was my concern and infact I have static wakelock implemented already because `startService()` is not synchronous. The code in question is just the sample code to explain. I was just curious if its the right scenario to acquire wakelock. Because I couldn't find many samples using it and its hard to produce the problem manually. – M-Wajeeh Dec 02 '13 at 16:50
  • @M-WaJeEh: so you start your service _with a static method inside on receive that also acquires the lock_ ? – Mr_and_Mrs_D Dec 02 '13 at 16:52
  • yes, that static method is responsible for starting `IntentService` but it acquires a wakelock before calling `startService()`. So the lock is static as well. – M-Wajeeh Dec 02 '13 at 16:56
  • which is right way, right? Its just that our app was showing a bit more wake lock time then we expect it to have. We are using Wake lock detector apps and also analyzing from Battery option from Android Settings. So I thought why not get a social validation as well. – M-Wajeeh Dec 02 '13 at 17:00
  • @M-WaJeEh: great still you may be better of with WIS - see :http://stackoverflow.com/a/17496029/281545 for the skeleton (which is what you do hopefully) and http://stackoverflow.com/questions/20074035/wakefulintentservice-implementation-clarifications for some fine points – Mr_and_Mrs_D Dec 02 '13 at 17:01
  • 1
    yes `WakefulIntentService` is doing same thing as well, it just have some utility methods for `AlarmManager` which we don't need. Thank you for your time brother. – M-Wajeeh Dec 02 '13 at 17:05
2

Method onReceive() is running on the main application thread and you do not know how long insertInDatabase() will take. Use an IntentService for doing the database insert and scheduling your alarms. The IntentService will call your onHandleIntent() on a background thread, so you can take the time you need, and the service automatically goes away when onHandleIntent() completes.

public class MyIntentService extends IntentService {

    @Override
    protected void onHandleIntent(Intent intent) {
        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
        final WakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, wakelockName); 
        wakeLock.acquire();
        wl.acquire();
        try { 
            SQLiteDatabase db = helper.getWritableDatabase();
            ContentValues cv = new ContentValues();
            // insert data in database here  
        } finally {
            wakeLock.release();
        }
    }
}

To start IntentService from BroadcastReceiver use AlarmManager. IntentService work as queue pattern and you don't need to worry about synchronicity of operations.

Added after discussion in comments:

Your code example does not say from what place you call PARTIAL_WAKE_LOCK. The short answer is PARTIAL_WAKE_LOCK is not needed in the BroadcastReciever and PARTIAL_WAKE_LOCK is needed in the IntentService. Maybe this will help BroadcastReceiver, Service and Wakelock

Community
  • 1
  • 1
Paha
  • 864
  • 7
  • 15
  • Thanks for the answer but I guess you have missed my point here, I am already launching an `IntentService` in `onReceive()`. My question is do I need `PARTIAL_WAKE_LOCK` here or not? – M-Wajeeh Dec 02 '13 at 06:29
  • Let me clarify that in question as well, although I used the word asynchronously. – M-Wajeeh Dec 02 '13 at 06:32
  • @M-WaJeEh I updated the answer by adding some information. Maybe I not fully understand your question, please give details, if you do not find an answer. – Paha Dec 02 '13 at 07:01
  • My question is do I need `PARTIAL_WAKE_LOCK` here or not? My question is not about internal working of `IntentService` or is `onRecive()` is called on UI thread or not by default etc. In other words, my question is "If in deep sleep, Android wakes up send a broadcast. Can it go to sleep immediately again? even tough I launched a service from `onReceive()`? Will Android wait for my service to finish or do I need to explicitly ask for `PARTIAL_WAKE_LOCK`." I guess I can't be more clearer that that. – M-Wajeeh Dec 02 '13 at 10:42
  • @M-WaJeEh Your code example does not say from what place you call PARTIAL_WAKE_LOCK. The short answer is LOCK is not needed in the BroadcastReciever and LOCK is needed in the IntentService. Maybe this will help http://stackoverflow.com/questions/5681071/broadcastreceiver-service-and-wakelock – Paha Dec 02 '13 at 12:42
  • Please post your last comment as answer so I can accept it. Thanks for the link. All I needed was asocial validation to be sure that I am doing things correctly. – M-Wajeeh Dec 02 '13 at 12:53