blog

Android Oによるバックグラウンド・サービスの制限

サービスにはインターフェースがなく、バックグラウンドで実行されるため、デバイスのリソースを消費し、リソースの使用量が多すぎてデバイスがスムーズに動作しないなど、ユーザーエクスペリエンスが低下する可能性...

Mar 16, 2020 · 4 min. read
シェア

Service

サービスにはインターフェイスがなく、バックグラウンドで実行されるため、デバイスのリソースを消費し、リソースの使用量が多すぎるなど、ユーザーエクスペリエンスが低下し、デバイスがスムーズに動作しなくなる可能性があります。この問題を軽減するために、Android Oバージョンではバックグラウンドサービスにいくつかの制限が課せられています。ただし、この制限はバックグラウンドサービスのみに適用され、フォアグラウンドサービスは影響を受けません。

フロントエンド・アプリケーションとは

バックエンド・サービスの制限を説明するには、まず、フロントエンド・アプリケーションとは何か、バックエンド・アプリケーションとは何かを知る必要があります。

フロントエンド・アプリケーションは、以下のいずれかの条件を満たす必要があります。

  1. レジューム状態でもポーズ状態でも、目に見えるアクティビティがあります。
  2. FrontendServiceがあります。
  3. サービスをバインドするか、ContentProviderを使用して、現在のアプリに接続する他のアプリがあります。

フロントエンドサービスとバックグラウンドサービス

では、フロントエンド・サービスとバックエンド・サービスをどのように区別するのでしょうか?

フォアグラウンドサービスは通知を送信するため、ユーザーはサービスが実行されていることを認識できますが、バックグラウンドサービスには通知がないため、ユーザーはサービスが実行されていることを認識できません。

では、フロントエンドのサービスとバックエンドのサービスはどのように開始されるのでしょうか?

Context.startService()バックグラウンド・サービスの場合は簡単です。

フォアグラウンドサービスの場合は、少し複雑です。Context.startService()Service.startForeground()しかし、Android 8.0以降、バックグラウンドアプリがバックグラウンドServiceを作成することが制限され、同じ方法でバックグラウンドServiceをフォアグラウンドServiceに昇格させることができなくなりました。Context.startForegroundService()Service.startForeground()Android 8.0では、バックグラウンドアプリがフォアグラウンドサービスを作成できない問題を解決するため、フォアグラウンドサービスを直接起動する新しい方法を導入しましたが、システムがこのフォアグラウンドサービスを作成する際、アプリは5秒以内に通知を表示するよう呼び出す必要があり、そうでない場合、システムはこのフォアグラウンドサービスを停止し、ANRをポップアップ表示します。

android.permission.FOREGROUND_SERVICEAndroid 9.0から、フォアグラウンドServiceを作成する場合は、AndroidManifest.xmlでパーミッションも宣言する必要があります。 これは、システムが自動的にアプリに付与する共通のパーミッションです。これを行わないと、例外がスローされます。

フロントエンドサービスの作成方法の例を以下に示します。

まず、アプリのターゲットバージョンがAndroid 10(API 29)である場合、マニフェストファイルでパーミッションを宣言する必要があります。

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

Android 8.0との互換性を保つため、コードは次のようになります。

 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 mIntent = new Intent(this, MyService.class);
 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
 startForegroundService(mIntent);
 } else {
 startService(mIntent);
 }
 }

アクティビティのonDestroy()でstopService()を呼び出すこともできますし、ServiceのstopSelf()を呼び出すこともできます。どちらを呼び出すかは、具体的な要件に応じて選択する必要があります。

サービスが作成されたらService.startForeground()

 public void onCreate() {
 super.onCreate();
 // 通知を送信し、サービスをフォアグラウンドに置く
 NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
 // アンドロイド8より.0開始するには、通知チャネルを登録する必要がある
 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
 NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID,
 "Service notification channel", NotificationManager.IMPORTANCE_DEFAULT);
 notificationManager.createNotificationChannel(notificationChannel);
 }
 NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
 .setSmallIcon(R.mipmap.ic_launcher)
 .setContentTitle("Service");
 // 最初のパラメーターを0にすることはできない。
 startForeground(666, builder.build());
 }

バックグラウンドサービスの制限

アプリがフォアグラウンドにあるときは、バックグラウンド・サービスを自由に作成して使用できます。アプリがバックグラウンドにある場合、サービスを作成して使用できるのは数分のウィンドウだけです。このウィンドウが終わると、システムはアプリをアイドル状態とみなし、アプリのバックグラウンド・サービスを停止します。

バックグラウンドサービスの制限の解決

公式の推奨は、バックグラウンドServiceを置き換えるためにJobSchedulerを使用することであり、公式はまた、アプリがフォアグラウンドで実行されていなくても、現在のユーザーが友人から共有されたイメージを受け取ったかどうかを検出する必要があるギャラリーアプリの例を示しました。Android 8.0では、アプリのクラウドストレージを検出するためにバックグラウンドのServiceを使用することができましたが、これには問題がありました。しかし、Android 8.0からは、バックグラウンドサービスの代わりにJobSchedulerを使用し、定期的にタスクを開始し、サーバーに照会を行い、終了します。バックグラウンドのサービスと比べて、消費するリソースが大幅に少なくなり、間接的に電話のパフォーマンスが向上します。

JobSchedulerの使い方については、次回の記事でイメージをダウンロードするケーススタディを紹介します。

Read next

ONE------Java の基本

ポリモーフィズムとは、同じ操作を異なるオブジェクトに適用すると異なる結果が得られることを意味します。 オーバーロードとオーバーライドは、Java ポリモーフィズムの異なる表現方法です。 - の場合、基本データ型の変数に作用する場合は、格納されている「値」が等しいかどうかを直接比較します。 これが参照型の変数に作用する場合、比較はその変数が指すオブジェクト間で行われます。

Mar 15, 2020 · 8 min read