※Android4.4系を対象にしたアプリ開発のメモになります。現在は変わっている可能性が高いです。
1年前にAndroidアプリを開発していた際に、Push機能やらなにやらの追加で起動後のActivityが意図しない物に変わっていた。
これは起動時のIntentやアプリの状況(バックグラウンドに存在するか否か)が関係していて、余計なIntentFlagを排除する処理を加えて強引に解決した記憶がある。
その際にタスク一覧から起動した時とホーム画面のアイコンから起動した時、Pushから起動したときなど、色々なケースでActivityを起動し、ActivityやIntentFlagについて調べたものがこちらになる。
開発から離れてしまったが、その時のメモが残っていたので供養を兼ねて公開しておく。
参考にしたページ
- IntentのCategoryとExtraとFlagの一覧表を作ってみたよ - hyoromoのブログ http://hyoromo.hatenablog.com/entry/20091003/1254590170
Intent | Android Developers http://developer.android.com/intl/ja/reference/android/content/Intent.html - GC: RecentsPanelView - com.android.systemui.recent.RecentsPanelView (.java) - GrepCode Class Source http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.2_r1/com/android/systemui/recent/RecentsPanelView.java#RecentsPanelView.simulateClick%28int%29
- GC: ActivityManager - android.app.ActivityManager (.java) - GrepCode Class Source http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.2_r1/android/app/ActivityManager.java#ActivityManager.setFrontActivityScreenCompatMode%28int%29
- GC: PendingIntent - android.app.PendingIntent (.java) - GrepCode Class Source http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4.4_r1/android/app/PendingIntent.java#PendingIntent.send%28android.content.Context%2Cint%2Candroid.content.Intent%2Candroid.app.PendingIntent.OnFinished%2Candroid.os.Handler%29
タスク一覧について
- ActivityManagerというのが走ってる
- ホーム画面(com.sonyericsson.home/com.sonymobile.home.HomeActivity)などに遷移する際に、コイツからIntentが投げられてるっぽい
- ホームボタン押下時
ActivityManager﹕ START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10200000 cmp=com.sonyericsson.home/com.sonymobile.home.HomeActivity} - アプリアイコンから起動時
ActivityManager﹕ START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=jp.co.my.application/.screen.splash.SplashActivity}
- ホームアイコンからはaction.MAIN,category.HOMEのIntentが発行されてアプリが起動
- タスク一覧からの起動
- ActivityManager﹕ START u0 {act=com.android.systemui.recent.action.TOGGLE_RECENTS flg=0x10800000 cmp=com.android.systemui/.recent.RecentsActivity
- RecentsActivityというActivityが管理してるっぽい
- ActivityManager﹕ START u0 {act=com.android.systemui.recent.action.TOGGLE_RECENTS flg=0x10800000 cmp=com.android.systemui/.recent.RecentsActivity
RecentsActivityについて
-
RecentsPanelViewというListViewっぽいのを持ってて、ApplicationId(taskId)とかサムネを持ってるのでタスク一覧はこれっぽい
-
RecentsPanelViewのアイテムが選択(handleOnClick)されると、ActivityManagerから該当するtaskIdを持つアプリをフォアグラウンドにするっぽい
(moveTaskToFront(int taskId, int flags, Bundle options) というメソッドが呼ばれる)- バックグラウンドで動作しているかによって呼ばれるのは異なる
- していない場合はActivityManagerの持つIntentを使ってアプリを起動
- その時のフラグとかはこんな感じ
intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY| Intent.FLAG_ACTIVITY_TASK_ON_HOME| Intent.FLAG_ACTIVITY_NEW_TASK) - 新規に開始する場合はログが出る(Log.v(TAG, "Starting activity " + intent))
- バックグラウンドで動作しているかによって呼ばれるのは異なる
-
ActivityManagerのRecentTaskInfoクラスがParcelable...
- もちろんIntent持ってる
起動時のIntentについて検めて見た
アプリアイコンから起動
V/SplashActivity﹕ Intent[@45c1c288] content:
V/SplashActivity﹕ Action : android.intent.action.MAIN
V/SplashActivity﹕ Category : {android.intent.category.LAUNCHER}
V/SplashActivity﹕ Data : null
V/SplashActivity﹕ Component: jp.co.my.application/jp.co.my.application.screen.splash.SplashActivity
V/SplashActivity﹕ Flags : 10000001000000000000000000000
V/SplashActivity﹕ Flag : FLAG_RECEIVER_FOREGROUND
V/SplashActivity﹕ Flag : FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
V/SplashActivity﹕ HasExtras: false
MainActivityに遷移
V/MainActivity﹕ Intent[@45c8fef8] content:
V/MainActivity﹕ Action : null
V/MainActivity﹕ Category : null
V/MainActivity﹕ Data : null
V/MainActivity﹕ Component: jp.co.my.application/jp.co.my.application.screen.main.controller.MainActivity
V/MainActivity﹕ Flags : 0
V/MainActivity﹕ HasExtras: false
タスク一覧から起動
V/SplashActivity﹕ Intent[@45c4f890] content:
V/SplashActivity﹕ Action : android.intent.action.MAIN
V/SplashActivity﹕ Category : {android.intent.category.LAUNCHER}
V/SplashActivity﹕ Data : null
V/SplashActivity﹕ Component: jp.co.my.application/jp.co.my.application.screen.splash.SplashActivity
V/SplashActivity﹕ Flags : 10000000100000100000000000000
V/SplashActivity﹕ Flag : FLAG_ACTIVITY_TASK_ON_HOME
V/SplashActivity﹕ Flag : FLAG_RECEIVER_FOREGROUND
V/SplashActivity﹕ Flag : FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
V/SplashActivity﹕ HasExtras: false
2回め
V/SplashActivity﹕ Intent[@45743a58] content:
V/SplashActivity﹕ Action : android.intent.action.MAIN
V/SplashActivity﹕ Category : {android.intent.category.LAUNCHER}
V/SplashActivity﹕ Data : null
V/SplashActivity﹕ Component: jp.co.my.application/jp.co.my.application.screen.splash.SplashActivity
V/SplashActivity﹕ Flags : 10000001100000100000000000000
V/SplashActivity﹕ Flag : FLAG_ACTIVITY_TASK_ON_HOME
V/SplashActivity﹕ Flag : FLAG_RECEIVER_FOREGROUND
V/SplashActivity﹕ Flag : FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
V/SplashActivity﹕ Flag : FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
V/SplashActivity﹕ HasExtras: false
MainActivityに遷移
V/MainActivity﹕ Intent[@4590bff0] content:
V/MainActivity﹕ Action : null
V/MainActivity﹕ Category : null
V/MainActivity﹕ Data : null
V/MainActivity﹕ Component: jp.co.my.application/jp.co.my.application.screen.main.controller.MainActivity
V/MainActivity﹕ Flags : 0
V/MainActivity﹕ HasExtras: false
V/MainActivity﹕ Flags : 0
バックグラウンドに居ない時
V/SplashActivity﹕ Intent[@426ca1c0] content:
V/SplashActivity﹕ Action : android.intent.action.MAIN
V/SplashActivity﹕ Category : {android.intent.category.LAUNCHER}
V/SplashActivity﹕ Data : null
V/SplashActivity﹕ Component: jp.co.my.application/jp.co.my.application.screen.splash.SplashActivity
V/SplashActivity﹕ Flags : 10000001000000000000000000000
V/SplashActivity﹕ Flag : FLAG_RECEIVER_FOREGROUND
V/SplashActivity﹕ Flag : FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
V/SplashActivity﹕ HasExtras: false
Pushの開封
D/MyApplication﹕ [MainActivity#onCreate:64] : ---init----
V/MainActivity﹕ Intent[@45e7a560] content:
V/MainActivity﹕ Action : null
V/MainActivity﹕ Category : null
V/MainActivity﹕ Data : null
V/MainActivity﹕ Component: jp.co.my.application/jp.co.my.application.screen.main.controller.MainActivity
V/MainActivity﹕ Flags : 10000000000001000000000000000
V/MainActivity﹕ Flag : FLAG_ACTIVITY_CLEAR_TASK
V/MainActivity﹕ Flag : FLAG_RECEIVER_FOREGROUND
V/MainActivity﹕ HasExtras: true
V/MainActivity﹕ Extra[push_action] :jp.co.my.application.common.model.PushObject@458edf90
開封後にタスク一覧から起動
V/MainActivity﹕ Intent[@45898af8] content:
V/MainActivity﹕ Action : null
V/MainActivity﹕ Category : null
V/MainActivity﹕ Data : null
V/MainActivity﹕ Component: jp.co.my.application/jp.co.my.application.screen.main.controller.MainActivity
V/MainActivity﹕ Flags : 10000000100001100000000000000
V/MainActivity﹕ Flag : FLAG_ACTIVITY_TASK_ON_HOME
V/MainActivity﹕ Flag : FLAG_ACTIVITY_CLEAR_TASK
V/MainActivity﹕ Flag : FLAG_RECEIVER_FOREGROUND
V/MainActivity﹕ Flag : FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
V/MainActivity﹕ HasExtras: true
V/MainActivity﹕ Extra[push_action] :jp.co.my.application.common.model.PushObject@45bd6480
タスク一覧に居ない場合のPushの開封
V/MainActivity﹕ Intent[@44c13d98] content:
V/MainActivity﹕ Action : null
V/MainActivity﹕ Category : null
V/MainActivity﹕ Data : null
V/MainActivity﹕ Component: jp.co.my.application/jp.co.my.application.screen.main.controller.MainActivity
V/MainActivity﹕ Flags : 10000000000001000000000000000
V/MainActivity﹕ Flag : FLAG_ACTIVITY_CLEAR_TASK
V/MainActivity﹕ Flag : FLAG_RECEIVER_FOREGROUND
V/MainActivity﹕ HasExtras: true
V/MainActivity﹕ Extra[push_action] :jp.co.my.application.common.model.PushObject@44d730b8
まとめ
- MainActivityがPush開封後にタスク一覧から起動する場合、意図しない遷移が発生する
- IntentにPushを受け取った時に作成したIntentが残っている
- Push開封後のタスク一覧から起動のIntentには、FLAG_ACTIVITY_LAUNCHED_FROM_HISTORYとFLAG_ACTIVITY_TASK_ON_HOMEが増えている
- Pushに関係ない場合のタスク一覧から起動した場合もこれらのFlagが付与されているので、一覧から起動したときの挙動と思われ(主にFROM_HISTORY)
- Push開封のIntent処理の際に、このFlagでifすれば対処は可能と思われる