2011年11月8日火曜日

【Android】RebootとkillBackgroundProcess

端末をとあるタイミングで自動的に再起動させたい。

という依頼から始まった今回の模索。
結果としては特定のプロセスを停止させるということで落ち着いたわけですが、ちょっとばかり回り道をしてしまいました。

今回はそれに関してメモです。
まず、
端末を定期的に再起動させたい。
というオーダーがありました。
が、その辺はぐりむさん。とりあえず方法は前に調べたことがありました。



必要な権限はこんな感じです。
android.permission.REBOOT

コードはこんな感じだと思います。
PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
pm.reboot("ほむほむ");

こんな感じで大丈夫であろう、と。

ところが。
rootedじゃないとこれ、使えないんですよ。
ええ。

その端末はコンシューマな端末ではないのでrootくらい取らせてくれるだろうと思っていたのですが、ベンダーに問い合わせたところ、返事は
「ヤだ。」
というツレないご返答でした。

そこで、あれこれ聞いているうちに、実は特定のプロセスを再起動させたいだけであることが判明しました。
そういう事は早く言ってください。まったくもう。

では特定のプロセスを落とす方法を模索します。
Android2.2以降ではBackgroudProcessしか落とせない様です。

じゃあ、今Frontに居るこいつをどうやって落とすか。思いついた答えは
Home画面を呼び出して無理やりBackgroundにしちゃったらどうなの?
でした。

必要な権限はこんな感じです。
android.permission.KILL_BACKGROUND_PROCESSES

コードはこんな感じです。
// Homeを呼び出すよ
Intent homeCallIntent = new Intent(Intent.ACTION_MAIN);
homeCallIntent.addCategory(Intent.CATEGORY_HOME);
homeCallIntent.addFlags(
        Intent.FLAG_ACTIVITY_NEW_TASK |
        Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
context.startActivity(homeCallIntent);

// Homeの起動を待つため1000msのwaitを挟む
try
{
    Thread.sleep(1000);
}
catch (InterruptedException e1)
{
    e1.printStackTrace();
}

// 起動しているプロセスのパッケージ名を指定して停止させる
ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
am.killBackgroundProcesses(PACKAGE_NAME);

これで無事、特定のプロセスを停止させることが出来ました。
#ウエイト入れてます。入れずにやってうまく行かなかったので。。。

が、新たな問題が勃発。
それは叉の機会に。

2 件のコメント :

  1. いつもお世話になっています。TKと申します。
    現在、アプリ開発中で、自分のアプリから別のアプリをボタンを押して起動させるアプリを作成しています。
    その際に戻るボタンでは自分のアプリには戻さないようにしていて、ノーティフィケーションを発生させて、戻る場合はそこからか再度アプリを起動させようとしています。そこからアプリを起動した場合に、バックキーで終了するとどうしてもその別のアプリに戻ってしまい、これをタスクを切ることで防ぎたいと考えています。実際に、ノーティフィケーションで起動した際にタスクマネージャーでそのほかのアプリのタスクを切ってから戻るボタンを押せばホーム画面が出ることは分かっているので自作アプリの戻るボタンを押したときにその別のアプリのタスクを切ろうとこのページを参考に行っていますがうまくいきません。
    特に、(ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);の場所のcontextをどうすればいいのかが分かりません、onKeyDownメソッド内にどのコンテクストを示せばいいのか…
    何かアドバイスを頂けたらと思います。よろしくお願いします。

    返信削除
    返信
    1. いつもご覧いただき有り難うございます。
      ちゃんと理解できておらず、間違った見解で有る可能性もありますのでご容赦ください。

      まず、今回言われているアプリというものが自アプリ、他アプリの2つだと仮定しています。

      ・自アプリは他アプリを起動する。
      ・自アプリは他アプリを起動した時にNotificationを登録する。
      ・他アプリの振る舞いについては不明。
      ・Notificationで自アプリを起動した際、TaskManagerアプリ?で他のアプリを停止させた後にバックキーを押すとHomeに戻る。
      ・【目的】自アプリでバックキーを押した時はHomeに戻る。

      まず前提としてAndroidのバックキーはActivityを終了させますがProcessの終了はOSの制御に依存しています。
      自アプリ起動中に他のProcessを停止させるとHomeが出てくるのはおそらくそれが理由ではないですかね?

      この文章内で書いているcontextはBroadcastReceiverが受け取ったonReceiveの引数です。
      Serviceを起動していて、ある条件の時にIntentを飛ばし、このBroadcastReceiverを呼び出しています。
      TKさんの場合では恐らく自アプリのContextを拾われるとよいかと思います。

      まず自アプリに、自アプリ以外のProcessを停止させる機能を適当なボタンをつけてテストしてみては如何でしょう。

      あと余談ですがこの文中のSleep処理はいい方法では無いのでお勧めしません。
      BroadcastReceiverは実行しているActivityと同じThreadで動いています。UIを持つアプリの主ActivityでSleepさせたらANR等でOSが怒る可能性があります。

      削除