BOOT_COMPLETEDレシーバー内でIntentServiceを開始しようとしていますが、Android O(API 26)で次のようになります:
Java.lang.RuntimeException:
Java.lang.IllegalStateException:
Not allowed to start service Intent { act=intent.action.update cmp=packageName.services.OwnService }:
app is in background
(メッセージは1行ですが、この方法で読みやすくなります)
これを正しい方法で行うにはどうすればよいですか?
ブログ投稿 で説明したいくつかのオプションを次に示します。
_ACTION_BOOT_COMPLETED
_ブロードキャストを受信するBroadcastReceiver
は、Android 8.0+の場合、startForegroundService()
の代わりにstartService()
を呼び出すことができます。
_import Android.content.BroadcastReceiver;
import Android.content.Context;
import Android.content.Intent;
import Android.os.Build;
public class OnBootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent i=new Intent(context, TestIntentService.class);
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O) {
context.startForegroundService(i);
}
else {
context.startService(i);
}
}
}
_
サービスが実際にstartForeground()
を呼び出さなくても、これはある程度機能することに注意してください。 「これを行うためのANR間隔に相当する」startForeground()
を呼び出すための時間枠が与えられます。作業が1ミリ秒より長く、数秒より短い場合、Notification
およびstartForeground()
呼び出しをスキップできます。ただし、LogCatでエラーが発生します。
_E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.commonsware.myapplication, PID: 5991
Android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground()
at Android.app.ActivityThread$H.handleMessage(ActivityThread.Java:1775)
at Android.os.Handler.dispatchMessage(Handler.Java:105)
at Android.os.Looper.loop(Looper.Java:164)
at Android.app.ActivityThread.main(ActivityThread.Java:6541)
at Java.lang.reflect.Method.invoke(Native Method)
at com.Android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.Java:240)
at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:767)
_
もちろん、Notification
を短くすることを気にしない場合は、Androidが期待するとおりにstartForeground()
を使用することを歓迎します。この場合、バックグラウンドで作業を行うことができます通常、ユーザーの通知シェードに表示されるエントリはありますが。
BroadcastReceiver
はAPIレベル11以降goAsync()
を提供しています。これにより、レシーバーはメインアプリケーションスレッドから作業を行うことができるため、IntentService
を完全に削除し、 BroadcastReceiver
にコード化します。 ANRタイムアウト期間はまだ残っていますが、メインアプリケーションスレッドを拘束することはありません。これは、同じ時間制限があるが厄介なエラーを回避する限り、最初の回避策よりも優れています。ただし、ある程度の手直しが必要です。
作業に数秒以上かかる場合andNotification
を避けたい場合は、コードを修正してJobService
を実装し、JobScheduler
。これには、他の条件が満たされた場合にのみ制御できるという利点があります(たとえば、使用可能なインターネット接続がある)。ただし、これには書き換えが必要なだけでなく、JobScheduler
はAndroid 5.0+でのみ使用できるため、minSdkVersion
が21未満の場合は、他の古いデバイスでのソリューション。
[〜#〜] update [〜#〜]:Eugen Pechanec 指摘JobIntentService
、これは興味深いJobService
/IntentService
マッシュアップ。
Android O動作の変更に関するドキュメント https://developer.Android.com/preview/features/background.html#services の次のセクションを確認してください。
アプリがバックグラウンドサービスを開始できるタイミングが制限されるようになりました。