web-dev-qa-db-ja.com

Android Oおよびバックグラウンドの制限により、単純なアラーム通知が防止されます

私自身のアプリは、2016年のGoogle I/Oアプリで示されているものとまったく同じ手法を使用しています。 ソースを参照

通知を使用して、非常に特定の時点でユーザーに通知する必要があります。

このために、AlarmManagerを使用してデバイスを正しい時点でウェイクします:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, alarmTime, pendingIntent);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KitKat) {
        am.setExact(AlarmManager.RTC_WAKEUP, alarmTime, pendingIntent);
    } else {
        am.set(AlarmManager.RTC_WAKEUP, alarmTime, pendingIntent);
    }

pendingIntentは次のように作成されます。

    final Intent intent = new Intent(MyAlarmService.ACTION_NOTIFY_RIDE, null, this, MyAlarmService.class);
    pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);

さて、私のMyAlarmServiceクラスは単純なIntentServiceであり、ユーザーへの通知を作成するためだけにウェイクアップを処理します。

ログに記録されるメッセージは次のとおりです。

W/ActivityManager: Background start not allowed: service Intent { act=xxx.xxx.xxx.action.NOTIFY_RIDE flg=0x4 cmp=xxx.xxx.xxx./xxx.xxx.xxx.service.MyAlarmService (has extras) } 

今、Google自身の実装は明らかに壊れています-重いバックグラウンド作業をしたくないが、このテクニックはもう使用できません。しかし、その後、非常に特定の時点でユーザーをどのように起こすのですか? (私のアプリを目覚まし時計と考えてください)

15
Zordid

私の質問への答えは単純明快です。

サービスを使用して通知を表示する代わりに(GoogleがIOアプリをスケジュールする!)で行うように)、BroadcastReceiverを使用してください!

GoogleがなぜIntentServiceを使用したのかはわかりませんが、今はAndroid O、これはバックグラウンド実行の制限により、もう機能していません。

ただし、BroadcastReceiverは、まだ少しの間実行され、通知を表示できます。

Googleが最初にIntentServiceを使用した理由を誰かが教えてくれたらボーナスポイント... Googleは彼らが何をしているのか知っていると思ったので、これを理解するのに年齢がかかりました...

9
Zordid

しかし、その後、非常に特定の時点でユーザーをどのように起こすのですか? (私のアプリを目覚まし時計と考えてください)

まず、コードは正確ではありません。デバイスがDozeモードの場合、せいぜい+/- 10分しか期待できません。正確なタイミングが必要で、アプリが本当に目覚まし時計である場合は、setAlarmClock()を使用します。

既存のコードの場合、 APIレベル26以降でgetForegroundService()の代わりにgetService() を使用します。

8
CommonsWare

SyncAdapter/Job Schedulerを定期的に実行して同じビジネスロジックを実行することも考えられます。また、新しい定期的な同期を設定するには、アプリケーションの起動自体で初めて行うことができます。

0
MOHIT KUMAR