こんにちは〜ヾ(´ω`=´ω`)ノ
突然ですが、Android端末のroot化はご存知ですか? と聞くまでもありませんね。
Android端末をroot化する理由ってなにがあるんでしょうか。例えばhostsの中身を書き換えたかったり、アプリの一部を強制的にSDカードに移して内部容量を確保したいとか、hostsの中身を書き換えたいとか、フォントを変えたいとか、hostsの中身を書き換えたいとか……。
とまあ理由はともかく、root化されている端末が世の中にあることは事実です。そして端末を一目見て、root化されているかされていないかを判別することは不可能です。それを例えばアプリ内の処理で判別することはできるのでしょうか?
今回はそんなことを調べてみました。
結果、下記の方法で判別が可能なようです。
1. 実際にroot化端末しかできない処理を呼び出してみる。できなければ非root化端末。
1つ目から早々ですが、力技での解決です。ですがこれが一番手っ取り早い判別方法になります。
早速判別するためのソースコードを紹介します。
try {
ProcessBuilder processBuilder = new ProcessBuilder("su");
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
InputStream is = process.getInputStream();
try {
while(is.read() >= 0);
} finally {
process.destroy();
is.close();
}
} catch (IOException e) {
} catch (Exception e){
}
簡単に解説します。AndroidはLinuxベースのOSです。Linuxではsuコマンドを使用することでroot権限を取得できます。上記の処理は、アプリ上でsuコマンドを実行させているだけです。
通常のAndroid端末はroot権限を取得できないようになっているため、この処理はsuコマンドが実行できずExceptionが発生してします。ただしroot化端末に関しては、Superuserなどのアプリによってroot権限を取得できるようになっているので、Exceptionを呼び出すことなく処理を駆け抜けることができるのです。
ただし、root化端末とはいえ何でもかんでも処理を実行させると大変なことになるため、実行時には使用許可をとるためのダイアログが表示されます。

ものものしいですね。
わざわざroot化されているかというチェックをするだけなのに、ダイアログまで出すのは流石にやりすぎというか、ユーザーに嫌がらせしているだけにしか見えません。何か他に方法はないのでしょうか。
一応、ありました。Processのコンストラクタまでであれば、Superuserのダイアログも表示されず、非root化端末であればこの時点でExceptionを投げてくれるようです。
try {
Process process = Runtime.getRuntime().exec("su");
process.destroy();
} catch (IOException e) {
e.printStackTrace();
}
通常の端末ではsuバイナリが存在しないため、これだけでも確認できるようです。ただし開発者向けの端末ではsuバイナリがあるかもしれないので、誤判定してしまう可能性があります。でも多分それって、root化端末と同じ気がしますけれど。
とりあえず上記の処理だけで判別できそうな雰囲気ですが、ちょっと不安ですね。suコマンドを実行しようとしたログが出てきて「裏で何かLinuxコマンドを叩いてるぞ!」なんて思われた日には、大変です。
なんというか、こう、「私はただroot化してるかどうか、知りたいだけなんです!」というストレートな判断方法はないんでしょうか?
もうSuperuser自体がインストールされているか検索しちゃいましょう!とりあえず現在のSuperuserは、通常com.noshufou.android.suというパッケージ名で配布されているようです。
2. Superuserがインストールされているか確認する。
getPackageManager().getApplicationInfo()でチェックしてしまいましょう。
try {
getPackageManager().getApplicationInfo("com.noshufou.android.su", 0);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
なにも難しいことはありません。NameNotFoundExceptionが発生すれば、Superuserがインストールされていない。ただそれだけです。
しかしSuperuser自体はソースコードも公開されているということもあり、中には別パッケージのSuperuserがインストールされている場合もあります。それにあてはまる場合では、このチェックは何の意味も成しません。
しかしここまで書いておいて、root化端末のチェックをするメリットはあるんでしょうか? 個人的な意見としては、独自でクラッシュレポートを実装する場合に、端末情報の取得の一つとして入れる価値はあるかもしれないですが、それ以外はないような気がします。root化しているかどうかよりも、OSや端末ごとの違いの方が、影響は大きいですからね。
ということで、上記の処理(suバイナリチェックとSuperuserアプリの確認)を組み込んだだけの、簡易root端末チェックアプリのソースコードをGithubに掲載しました。参考にどうぞ。
https://github.com/yamacraft/RootCheck

root化していないIS03で動作させた結果。こんな風にエラーが……なんでこんなに緑なんでしょう?

root化した某Xperia系端末。2つのチェックが素通りしています。
しかし2.3.xまでの頃は、特にROM(この表記の仕方がいつも気になってしかたない)の容量が少ないという理由がありましたが、最近はようやくROM(この表記の〜)も容量もGB単位になってきました。フォントが変えられないという理由はありますが、がんばってroot化しようという理由も減ってきてはいるんじゃないでしょうか。あとは端末設定からhostsファイルの権限を変えられるなり、直接書き換えられるようになれば……hosts……。
あ、エンジニアの山田でした。