PowerManager wakelock not waking device up from service

匿名 (未验证) 提交于 2019-12-03 01:10:02

问题:

I've an app that has a background service running every minute. I want the service to wake the device up if it's asleep. I am using a PowerManager but the device doesn't wake up. Any ideas why? Thanks in advance.

@Override protected void onHandleIntent(Intent intent) {     PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);     PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK,             "My Tag");     wl.acquire();     // do work as device is awake     wl.release(); } 

[edit1]

This is how i start the service from an Activity.

// get a Calendar object with current time Calendar cal = Calendar.getInstance(); // add 5 minutes to the calendar object cal.add(Calendar.MINUTE, 1); Intent intent = new Intent(getApplicationContext(), AlarmReceiver.class); intent.putExtra("alarm_message", "sending outstanding transactions"); // In reality, you would want to have a static variable for the // request code instead of 192837 PendingIntent sender = PendingIntent.getBroadcast(         getApplicationContext(), 192837, intent,         PendingIntent.FLAG_UPDATE_CURRENT); // Get the AlarmManager service AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE); // am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender); // 86400000 = 24 hours // 43200000 = 12 hours // 3600000 = 1hr // 1800000 = 30 mins // 300000 = 5 mins am.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),60000,sender); 

AlarmReceiver class

import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.widget.Toast; import android.os.Bundle;  public class AlarmReceiver extends BroadcastReceiver {      @Override     public void onReceive(Context context, Intent intent) {         try {              Bundle bundle = intent.getExtras();             String message = bundle.getString("alarm_message");             // Toast.makeText(context, message, Toast.LENGTH_SHORT).show();             Intent myIntent = new Intent(context,                     SendOutstandingTransactions.class);             myIntent.setAction("com.carefreegroup.startatboot.MyService");             context.startService(myIntent);         } catch (Exception e) {             Toast.makeText(                     context,                     "There was an error somewhere, but we still received an alarm",                     Toast.LENGTH_SHORT).show();             e.printStackTrace();         }     } } 

The following class calls the Activity which I want to start when the device is asleep.

SendOutstandingTransactions IntentService.

protected void onHandleIntent(Intent intent) {     PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);     PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK,             "My Tag");     wl.acquire();     if (hasMessageDisplayed == false) {         Intent i = new Intent(this, DisplayMessageActivity.class);         i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);         startActivity(i);     }     wl.release(); } 

[edit2]

@Override public void onDestroy() {     super.onDestroy();     PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE);     PowerManager.WakeLock wl = pm.newWakeLock(             PowerManager.PARTIAL_WAKE_LOCK, "com.something.alarm");     // Acquire the lock     if (wl.isHeld()) wl.release(); } 

回答1:

Either use Commonsware's WakefulIntentService or do this :

class YourService extends IntentService {      private static final String LOCK_NAME = YourService.class.getName()             + ".Lock";     private static volatile WakeLock lockStatic = null; // notice static      synchronized private static PowerManager.WakeLock getLock(Context context) {         if (lockStatic == null) {             PowerManager mgr = (PowerManager) context                     .getSystemService(Context.POWER_SERVICE);             lockStatic = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,                     LOCK_NAME);             lockStatic.setReferenceCounted(true);         }         return (lockStatic);     }      public static void startYourService(Context ctxt, Intent i) { // STATIC          getLock(ctxt.getApplicationContext()).acquire();         ctxt.startService(i);     }      public YourService(String name) {         super(name);         setIntentRedelivery(true);     }      @Override     public int onStartCommand(Intent intent, int flags, int startId) {         PowerManager.WakeLock lock = getLock(this.getApplicationContext());         if (!lock.isHeld() || (flags & START_FLAG_REDELIVERY) != 0) {             lock.acquire();         }         super.onStartCommand(intent, flags, startId);         return (START_REDELIVER_INTENT);     }      @Override     protected void onHandleIntent(Intent intent) {         try {             // do your thing         } finally {             PowerManager.WakeLock lock = getLock(this.getApplicationContext());             if (lock.isHeld()) lock.release();         }     } } 

and in your receiver :

Bundle bundle = intent.getExtras(); String message = bundle.getString("alarm_message"); // Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); Intent myIntent = new Intent(context, SendOutstandingTransactions.class); myIntent.setAction("com.carefreegroup.startatboot.MyService"); YourService.startYourService(context, myIntent) 

which is actually the core from @CommonsWare WakefulIntentService (not sure about the START_FLAG_REDELIVERY, I should ask one of these days)



回答2:

You need to use an AlarmManager to get the wakelock, fire your service at a given time and let the service release the wakelock. The service itself ,even if running in background, could not be called because the CPU is already sleeping and won't execute your code.

Put this inside the onReceive of your AlarmManager:

         PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);          PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "com.something.alarm");          //Acquire the lock          System.out.println("+++ Acquiring Lock +++");           if(!wl.isHeld())             wl.acquire();            // Fire your service 

Then release the wakelock at the end of the execution of your service. This means that you have to call wl.release() inside your service, before it ends.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!