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

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メソッドで送信します。たったこれだけです。

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