【Android入門】デバイスがルート化(root化)されているかどうかを判定する方法
決済ゲートウェイを利用するアプリなど、一部のアプリケーションでは、セキュリティ上の理由からルート化(root化)された端末での実行を許可しないケースがあります。この記事では、Androidアプリが実行されている端末がルート化されているかどうかをプログラムで判定する方法を、サンプルコードとともに分かりやすく解説します。
手順1:新しいプロジェクトを作成する
Android Studioを起動し、メニューから「File」→「New Project」を選択します。必要な項目をすべて入力して、新しいプロジェクトを作成してください。
手順2:レイアウトファイルを編集する
res/layout/activity_main.xml に以下のコードを追加します。
<?xml version = "1.0" encoding = "utf-8"?> <LinearLayout xmlns:android = "https://schemas.android.com/apk/res/android" android:id = "@+id/parent" xmlns:tools = "https://schemas.android.com/tools" android:layout_width = "match_parent" android:layout_height = "match_parent" tools:context = ".MainActivity" android:gravity = "center" android:orientation = "vertical"> <TextView android:id = "@+id/rootFinder" android:layout_margin = "20dp" android:textAlignment = "center" android:layout_width = "match_parent" android:layout_height = "wrap_content" /> </LinearLayout>
このレイアウトでは、ルート状態の判定結果を表示するためのTextViewを1つ中央に配置しています。
手順3:MainActivity.java を実装する
src/MainActivity.java に以下のコードを追加します。
package com.example.andy.myapplication;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
int view = R.layout.activity_main;
TextView rootFinder;
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(view);
rootFinder = findViewById(R.id.rootFinder);
executeShellCommand("su");
}
private void executeShellCommand(String su) {
Process process = null;
try {
process = Runtime.getRuntime().exec(su);
rootFinder.setText("It is rooted device");
Toast.makeText(MainActivity.this, "It is rooted device", Toast.LENGTH_LONG).show();
} catch (Exception e) {
rootFinder.setText("It is not rooted device");
} finally {
if (process != null) {
try {
process.destroy();
} catch (Exception e) { }
}
}
}
}
このコードでは、suコマンドの実行を試みることで端末がルート化されているかどうかをテストし、その結果をTextViewに表示しています。
ルート化チェックの仕組み
ルート化の有無を判定しているのは、次のコード部分です。
executeShellCommand("su");
..........................................................................................
private void executeShellCommand(String su) {
Process process = null;
try {
process = Runtime.getRuntime().exec(su);
rootFinder.setText("It is rooted device");
Toast.makeText(MainActivity.this, "It is rooted device", Toast.LENGTH_LONG).show();
} catch (Exception e) {
rootFinder.setText("It is not rooted device");
} finally {
if (process != null) {
try {
process.destroy();
} catch (Exception e) { }
}
}
}
仕組みは非常にシンプルです。Runtime.getRuntime().exec("su") を呼び出して、スーパーユーザー権限を取得する「su」コマンドの実行を試みます。コマンドの実行に成功すればその端末はルート化されており、逆に例外が発生した場合は非ルート端末であると判断できます。また、finallyブロックでプロセスを確実に破棄することで、リソースリークを防いでいる点にも注目してください。
アプリを実行して動作を確認する
それでは、作成したアプリを実際に実行してみましょう。ここでは、実際のAndroid端末をパソコンに接続しているものとして説明を進めます。Android Studioでプロジェクト内のアクティビティファイルを開き、ツールバーの「Run」アイコンをクリックします。接続したモバイル端末を選択すると、端末の画面に判定結果が表示されます。

上記の実行結果を見ると、「It is not rooted device(ルート化されていない端末です)」というメッセージが表示されており、この端末はまだルート化されていないことが確認できます。ルート化された端末で実行した場合は、「It is rooted device」と表示されます。
なお、より厳密なルート検出が必要な実務では、suコマンドの存在確認に加えて、MagiskやSuperSUなどの代表的なルート管理アプリのパッケージ有無のチェック、test-keysによるビルド署名の確認、SafetyNet Attestation API(現在はPlay Integrity API)の活用なども併用されることが多いので、参考にしてみてください。
-
Androidでボイスメールが機能しない問題を解決する5つの方法
ボイスメールは、電話機に手が届かないときやバッテリーが切れてしまったときなどに非常に便利な機能です。電話の電源が入っていない、あるいは圏外で連絡がつかない状況でも、相手がボイスメールを残せるため、後からまとめて確認して対応することができます。大切な人との旅行中にスマホの電源を切りたいと思ったことはありませんか?事前にボイスメールを設定しておけば、重要な電話を見逃すことなく、後から折り返すことも可能です。ただし、それが実現できるのは、デバイス上でボイスメールが正常に動作している場合だけです。Androidスマホでボイスメールが機能せず、着信がボイスメールにつながらないと、とてもストレスを感じます
-
「Move to iOS」が動作しないときの対処法まとめ
AndroidからiPhoneへの機種変更をスムーズにするために、Appleは「Move to iOS」という専用アプリを提供しています。このアプリを使えば、Androidデバイス上のデータをiOSデバイスへ素早く簡単に移行できます。ほとんどの場合は問題なく動作しますが、ときにはうまく動かないこともあります。データ移行の途中で止まってしまう、接続が切れるといったトラブルに遭遇した方もいるでしょう。 原因はさまざま考えられます。たとえば、移行中にAndroid側が別のWi-Fiネットワークへ切り替わってしまった、あるいはiPhoneの容量を超える量のデータを移行しようとしている、などが挙げられ