2017-10-31  Android Java プログラミング

サービスからアクティビティを開始するときに時間がかかる問題を回避

Android アプリケーションのコンポーネントには、 アクティビティ、 サービス、 コンテンツ プロバイダ、 ブロードキャスト レシーバーの 4 種類があります。アクティビティは画面を持つコンポーネント、 サービスはバックグランドで動作するコンポーネントです。

アプリケーションの形態によっては、 バックグランドで動作しているサービスからアクティビティを開始して画面表示をしたい、 といったことがあります。

startActivity メソッドでインテントを送信することでアクティビティを開始する方法が良く知られていますが、 実はこの方法には状況によって 5 秒程度の時間がかかるという落とし穴があります。

インテントを送信してアクティビティを開始する例

Android ではインテントを送信することでアクティビティを開始することができます。はじめにアクティビティを開始するコード例を紹介しておきます。

たとえば、 マップ (Google Maps) を開始する場合は以下のようなコードを書きます。

マップ(Google Maps)を開始する例
Intent intent = new Intent(Intent.ACTION_MAIN); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setClassName( "com.google.android.apps.maps", "com.google.android.maps.MapsActivity"); context.startActivity(intent);

基本的にはこれで問題ないのですが、 このコードには HOME ボタンを押した直後は制限を受けるという問題があります。

HOMEボタンを押下後はアクティビティ開始が制限される

Android には HOME ボタンを押下してホーム画面に戻った直後 (5 秒間) は、 サービスからのアクティビティ開始が制限されるという仕様があります。

ユーザーがタッチ操作によってアプリを起動しようとした場合にはこのような制限はかかりません。

この制限を回避する方法についてインターネット上のコミュニティ各所で様々な議論がされており、 以前から android.permission.STOP_APP_SWITCHES パーミッションを付与すれば、 この 5 秒制限を受けなくなることは知られていました。

しかし、 android.permission.STOP_APP_SWITCHES の保護レベルは signatureOrSystem となっており、 このパーミッションを付与するために、 アプリにプラットフォーム署名をしたり、 root 権限を取得してアプリを /system/app/ に配置することが必要でした。事実上、 一般アプリでは android.permission.STOP_APP_SWITCHES パーミッションを付与することはできないといえます。

議論の中では他にも…

  • 必要な機能をアクティビティではなくサービスだけで実装すべきだ
  • アプリ自身をホームアプリにしてしまえばよい

といった意見も多いのですが、 これでは根本的な解決にはならないですよね。

PendingIntentならアクティビティ開始制限を受けない

どういった理由なのか分かりませんが、 PendingIntent を使うと HOME ボタン押下直後 5 秒間のアクティビティ開始制限を受けなくなります。

PendingIntent を使ってマップ (Google Maps) を開始するように書き換えたコードは以下の通りです。

PendingIntentを使ってマップ(Google Maps)を開始する例
Intent intent = new Intent(Intent.ACTION_MAIN); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setClassName( "com.google.android.apps.maps", "com.google.android.maps.MapsActivity"); PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0); pendingIntent.send();

従来通りにアクティビティ開始用のインテントを作成して、 startActivity で送信する代わりに PendingIntent でラップして send メソッドで送信します。たったこれだけです。

このとても簡単なコードの書き換えによって、 長年、 私達を悩ませ続けてきたアクティビティ開始制限を回避できてしまうなんて驚きですね。

Stack Overflow(参考)
Starting an activity from a service after HOME button pressed without the 5 seconds delay
最終更新日 2024-12-13
この記事を共有しませんか?
ブックマーク ポスト