初めに
こんにちは!DreamHanksのキムです。
今回はAndroidデバイスを使ってキオスク端末を作る方法について説明いたします。
Kiosk端末とは
キオスクとは、駅・空港・ホテル・商業施設などの公衆の場に設置されているインターネット接続のための情報端末を意味します。
Kioskアプリケーションの作り方
Activity.startLockTaskを使って、他の画面への移動を制限することができます。
簡単ですね!
…しかし、この方法だとユーザーが勝手にロックを解除して、他の画面に移動することができてしまいます。
Device Ownerとは
Androidにはデバイスを管理するための特別な権限を持ったDevice Ownerという管理者権限があります。
この権限は、もともと企業でデバイスを管理するための機能です。 例えば、ユーザーが勝手にGoogle Playからアプリをダウンロードしたり、設定を変えたりするなどの行為を防ぐことができます。
ただし、この権限を使うには、デバイスの初期化が必要です。
Device Ownerアプリの作り方
まずは、今のアプリをDevice Ownerにする必要があります。
Device Ownerアプリには、「DeviceAdminReceiver」と、Android 12以上の場合は以下2つのIntentを処理するActivityが必要です。
1. android.app.action.GET_PROVISIONING_MODE
2. android.app.action.ADMIN_POLICY_COMPLIANCE
1 2 3 4 5 |
public class DeviceAdminReceiver extends android.app.admin.DeviceAdminReceiver { public static ComponentName getComponentName(Context context) { return new ComponentName(context.getApplicationContext(), DeviceAdminReceiver.class); } } |
もともとはgetComponentNameも必要ありませんが、 後で使うために追加しました。
AndroidManifest.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<receiver android:name=".DeviceAdminReceiver" android:exported="true" android:description="@string/app_name" android:label="@string/app_name" android:permission="android.permission.BIND_DEVICE_ADMIN"> <meta-data android:name="android.app.device_admin" android:resource="@xml/device_admin_receiver" /> <intent-filter> <action android:name="android.app.action.DEVICE_ADMIN_ENABLED"/> </intent-filter> </receiver> |
res/xml/device_admin_receiver.xml:
1 2 3 4 |
<device-admin> <uses-policies> </uses-policies> </device-admin> |
テストをするにはこれでも十分です。
ただし、このままだとプロビジョニングできなくなってしまいますので、以下の2つのActivityを追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
public class AdminPolicyComplianceActivity extends Activity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setResult(RESULT_OK); finish(); } } public class GetProvisioningModeActivity extends Activity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (isManagedProfileIsAllowed()) { doProvision(); return; } // エラーメッセージ setContentView(R.layout.activity_provisioning_mode_unavailable); Button buttonCancel = findViewById(R.id.button_cancel); buttonCancel.setOnClickListener(this::onCancelPressed); } @Override public void onBackPressed() { setResult(RESULT_CANCELED); super.onBackPressed(); } private void onCancelPressed(View view) { this.onBackPressed(); } private boolean isManagedProfileIsAllowed() { ArrayList<Integer> allowedProvisioningModes = getIntent().getIntegerArrayListExtra(EXTRA_PROVISIONING_ALLOWED_PROVISIONING_MODES); if (allowedProvisioningModes == null || allowedProvisioningModes.isEmpty()) { return true; } return allowedProvisioningModes.contains(PROVISIONING_MODE_MANAGED_PROFILE); } private void doProvision() { final Intent intent = new Intent(); intent.putExtra(EXTRA_PROVISIONING_MODE, PROVISIONING_MODE_FULLY_MANAGED_DEVICE); setResult(RESULT_OK, intent); finish(); } } |
AndroidManifest.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<activity android:name=".GetProvisioningModeActivity" android:exported="true" android:permission="android.permission.BIND_DEVICE_ADMIN"> <intent-filter> <action android:name="android.app.action.GET_PROVISIONING_MODE" /> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity> <activity android:name=".AdminPolicyComplianceActivity" android:exported="true" android:permission="android.permission.BIND_DEVICE_ADMIN"> <intent-filter> <action android:name="android.app.action.ADMIN_POLICY_COMPLIANCE" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> |
AdminPolicyComplianceActivityはプロビジョニング中に色々設定できるActivityですが、簡単にするために省略しました。
GetProvisioningModeActivityは、このアプリケーションをどのモードでプロビジョニングするかを決定するためのActivityで、ユーザーがProfile OwnerとDevice Ownerのどちらかを選択できるようにするなどの動作ができます。
この記事ではDevice Owner権限が必要ですので、PROVISIONING_MODE_MANAGED_PROFILEを自動的に選択するようにしました。
Kiosk Activityの作成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@Override protected void onStart() { DevicePolicyManager policyManager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); policyManager.setLockTaskPackages( DeviceAdminReceiver.getComponentName(this), new String[] { getPackageName() } ); ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); if (activityManager.getLockTaskModeState() == ActivityManager.LOCK_TASK_MODE_NONE) { startLockTask(); } } |
プロビジョニング
プロビジョニング用QRコードを作ります。
1 2 3 4 5 6 7 |
{ "android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME": "com.company.package/.DeviceAdminReceiver", "android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM": "(checksum)", "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION": "https://.../app-release.apk", "android.app.extra.PROVISIONING_SKIP_ENCRYPTION" : true, "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED" : true } |
PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUMは以下のコマンドを実行して取得できます。
1 |
apksigner verify -print-certs app-release.apk | grep -Po "(?<=SHA-256 digest:) .*" | xxd -r -p | openssl base64 | tr -d '=' | tr -- '+/=' '-_' |
デバイスをファクトリーリセットして、初期画面(言語を選べる画面)で画面の空き領域をすばやく、6回ほどタッチすることでQRコードスキャン画面に進入できます。 このQRコードをスキャンすることでインストールできます。
終わりに
今回の記事は以上となります。
ご覧いただきありがとうございます。
コメント