【问题标题】:PowerManager wakelock not waking device up from servicePowerManager 唤醒锁未从服务中唤醒设备
【发布时间】:2013-07-04 13:02:30
【问题描述】:

我有一个应用程序,每分钟运行一次后台服务。我希望该服务在设备处于睡眠状态时将其唤醒。我正在使用 PowerManager,但设备没有唤醒。任何想法为什么?提前致谢。

@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();
}

[编辑1]

这就是我从 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 类

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();
        }
    }
}

下面的类调用我想在设备休眠时启动的Activity。

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();
}

[编辑2]

@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();
}

【问题讨论】:

  • 确实做到了,谢谢。

标签: android power-management android-wake-lock


【解决方案1】:

要么使用 Commonsware 的 WakefulIntentService,要么这样做:

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();
        }
    }
}

在你的接收器中:

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)

这实际上是来自@CommonsWare WakefulIntentService 的核心(不确定 START_FLAG_REDELIVERY,我应该问这些日子之一)

【讨论】:

    【解决方案2】:

    您需要使用 AlarmManager 来获取唤醒锁,在给定时间触发您的服务并让服务释放唤醒锁。服务本身,即使在后台运行,也无法调用,因为 CPU 已经在休眠,不会执行您的代码。

    把这个放在你的 AlarmManager 的 onReceive 中:

             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
    

    然后在服务执行结束时释放唤醒锁。这意味着您必须在服务结束之前调用 wl.release()。

    【讨论】:

    • 您好,我确实使用了 AlarmManager。我编辑了开头的帖子,向您展示我如何调用该服务。你能解释一下把唤醒锁代码放在哪里吗?谢谢
    • 我已按照您的建议将该代码放在 onReceive 中,并将代码放在我服务的 onDestroy 方法中的 [edit2] 中。它仍然没有唤醒手机。任何想法为什么?谢谢
    • 您确定警报已正确实例化和调用吗?如果不检查本教程,它肯定会帮助你:code4reference.com/2012/07/tutorial-on-android-alarmmanager
    • 您的答案并不总是有效,因为 CPU 可能会在 Receiver 返回和服务启动之间再次进入休眠状态。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多