web-dev-qa-db-ja.com

android AlarmManagerが電話を復帰させない

特定の時間にアクティビティを表示したい。このために、AlarmManagerを使用しています。デバイスが起動している場合は正常に機能しますが、スリープ状態にある場合は起動しません。

アラームを設定するための私のコード:

Calendar alarmTime = Calendar.getInstance();
alarmTime.set(Calendar.HOUR_OF_DAY, alarm.hour);
alarmTime.set(Calendar.MINUTE, alarm.minute);
alarmTime.set(Calendar.SECOND, 0);

if (alarmTime.before(now))
    alarmTime.add(Calendar.DAY_OF_MONTH, 1);

Intent intent = new Intent(ctxt, AlarmReceiver.class);
intent.putExtra("alarm", alarm);
PendingIntent sender = PendingIntent.getBroadcast(ctxt, alarm.id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC_WAKEUP, alarmTime.getTimeInMillis(), sender);

私の放送受信機:

@Override
public void onReceive(Context context, Intent intent) {
    try {

Bundle bundle = intent.getExtras();
final Alarm alarm = (Alarm) bundle.getSerializable("alarm");

Intent newIntent;
if (alarm.type.equals("regular")) {
    newIntent = new Intent(context, RegularAlarmActivity.class);
} else if (alarm.type.equals("password")) {
    newIntent = new Intent(context, PasswordAlarmActivity.class);
} else if (alarm.type.equals("movement")) {
    newIntent = new Intent(context, MovementAlarmActivity.class);
} else {
    throw new Exception("Unknown alarm type");
}
    newIntent.putExtra("alarm", alarm);
    newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(newIntent);

} catch (Exception e) {
    Toast.makeText(context, "There was an error somewhere, but we still received an alarm", Toast.LENGTH_SHORT).show();
    Log.e("AlarmReceiver", Log.getStackTraceString(e));
}
}

このコードはデバイスを起動しません。しかし、それをもう一度元に戻すと表示されます。画面をオンにする必要があります。この問題を手伝ってくれませんか?

26
Gabriel

私にも同様の問題があり、解決策はWakeLockerを使用することでした。これを行う必要があります(できれば、レシーバーの最初のものとして)。そうしないと、アラームを受信するとデバイスがウェイクアップしますが、context.startActivity(newIntent)の前に再びスリープ状態になります。と呼ばれます。 (私はそれが起こらないときの動作も観察したので、それは少し恣意的であるように思われます)簡単かつ迅速な答え:次のソースコードでWakeLockerという新しいクラスを作成します。

_package mypackage.test;

import Android.content.Context;
import Android.os.PowerManager;

public abstract class WakeLocker {
    private static PowerManager.WakeLock wakeLock;

    public static void acquire(Context ctx) {
        if (wakeLock != null) wakeLock.release();

        PowerManager pm = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE);
        wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK |
                PowerManager.ACQUIRE_CAUSES_WAKEUP |
                PowerManager.ON_AFTER_RELEASE, MainActivity.APP_TAG);
        wakeLock.acquire();
    }

    public static void release() {
        if (wakeLock != null) wakeLock.release(); wakeLock = null;
    }
}
_

そして、あなたのレシーバーで最初にWakeLocker.acquire(context);を呼び出します。補足:アラームが完了したら、WakeLocker.release();を呼び出すのも便利です。

56
user859593

ほとんどの場合、アラームがデバイスを起動しています。ただし、AlarmManagerブロードキャストでは画面がオンにならず、アクティビティが開始する前にデバイスがスリープ状態に戻る場合があります。

onReceive()を呼び出す前にstartActivity()WakeLockを取得し、ユーザーがアクティビティに応答した後にそのWakeLockを解放する必要があります。

30
CommonsWare

サービスの場合(おそらくアクティビティでも機能します)、WakefulBroadcastReceiverからAlarmReceiverを拡張します。インテントの処理中にWAKE_LOCKを取得します。

WakefulBroadcastReceiver docs- https://developer.Android.com/reference/Android/support/v4/content/WakefulBroadcastReceiver.html

デバイスのスリープ解除ガイドの維持- https://developer.Android.com/training/scheduling/wakelock.html

8
Kof