How to reboot android phones programmatically

Android 端末をプログラムで再起動させる方法について。

まず、プログラムでということに関わらず Android 端末を再起動させる方法はいくつかあります。

HOME + CALL + POWER キーを同時に押下する

ボタンの三つ同時押しですね。Xperia ( SO-01B )、Nexus One などは CALL キーがないのでこの手法は利用できません。

adb で接続して /system/bin/reboot を実行する

adb で接続できれば普通にいけるはずです。reboot コマンドのソースコードは・・・現在探しています。

なので、このコマンドをプログラムから実行すれば再起動できるのですが、root 権限が必要です。
例えば以下のプログラムなんかもそれっぽいですね。

詳細は後述しましょう。

PowerManager.reboot() メソッドを呼び出す

Android 2.2 ( froyo ) からは PowerManager.reboot() メソッドが利用できるようになりました。

REBOOT パーミッションをつけばいけますが、
このパーミッションにはシステム署名が必要になります。
よって、アプリにシステム署名を施せばいけます。
なので、マーケットアプリでは不可能だと思います。

なお、このメソッドの奥にいるのは android.os.Power クラスです。
これは Android 1.5 ( cupcake ) の時代からずっといます。
Java ではなく C で実装されていて、JNI で Java 側に機能を提供しています。

NDK を使って C で reboot() を呼び出す

結局 Linux なので、reboot() を呼び出せば再起動できます。

しかし、普通に呼び出しても EPREM で失敗します。
普通のアプリはこれを実行する権限を持っていないためです。

さきほどの PowerManager.reboot() や android.os.Power クラスを
たどっていくと、結局 Linux の reboot() 関数を実行しています。

PowerManager を経由して呼び出すと、
PowerManager を握っているプロセスに処理が依頼されて、
実行が成功するという仕組みです。

この方法がプログラムで再起動するためのもっとも適切な方法だと思います。
ただし、システム署名が必要なのでほとんどのアプリでは利用できないですね。
froyo からしか使えないというのも痛いです。
端末にプリインストールされるようなアプリの開発者なら別ですが・・・。

その他の方法

最後に紹介するのは裏技的なものです。

ここで出てくる以下のコードですね。

Intent i = new Intent(Intent.ACTION_REBOOT); 
i.putExtra("nowait", 1); 
i.putExtra("interval", 1); 
i.putExtra("window", 0); 
sendBroadcast(i); 

アプリにシステム署名を施せばいけます。

非公式な方法なのであまり推奨されませんが、
システム署名を得られるならば PowerManager.reboot() の次に手頃な方法だと思います。
最大の利点は、cupcake 以降で動作するという点でしょう。

ADP1 での実機確認も良好でした。

2010/08/14 追記

ちなみにこの方法は、Android 1.5 ( cupcake ) でしか通用しません。
Android 1.6 ( donut ) 以降では、Android フレームワーク側に修正が入り例外が発生します。

詳細は以下で説明されています。