JA1YADホーム>未分類Kotlinのcoroutinesを使ってUsbManagerのrequestPermissionをきれいに処理する2019年3月2日AndroidでUSBデバイスを直接制御したいと考える奇特な人はそう多くはないと思いますが、いざ制御するぞとなったときにぶち当たるのがUSBデバイスの制御権限の問題です。Androidは最近のバージョンに於いてはリソースのアクセス制限が厳しく、ユーザーの許可なしに物理デバイスにアクセスするのは不可能な構造になっています。そこで、開発者はユーザーに明示的に利用許可を求める必要があるわけです。デバイスの列挙ウォーミングアップとして、USBデバイスの検出方法について見ていきましょう。ここでは、MainActivityというアクティビティがデフォルトで起動されるという設定で行きます。outputLabelという名前のTextViewと、buttonという名前のButtonが既に追加されているものとします。以下のコードを見てください。}}これを実行してボタンを押すと、以下のような出力になるかと思います。目的のデバイスを検索して使います。この時点で取得できるUsbDeviceオブジェクトは何の権限も持っていません。そこで、ユーザーに明示的に権限を要求します。権限を要求するには、UsbManager.requestPermission(UsbDevice)メソッドを呼び出します。このメソッドを呼び出すと、権限要求の表示タスクがキューされ、UIスレッドの制御を返すと実際に確認ダイアログ的なものが表示されます。要求の結果はBroadcastIntentで返ってきます。よって、BroadcastReceiverをActivity内で登録してやらなければいけません。実際にやってみると以下のようになります。}}ご覧の通り、権限要求部分と要求の結果を受け取る部分が完全に分かれてしまいます。これはなんともやりにくい。//許可されたときの処理}みたいな感じで書きたいわけです。上記のような書き方を実現する方法として、Kotlinにはコルーチンというものがあります。コルーチンとは、簡単に言うと「指定した箇所で処理の中断・再開が可能な関数」です。雰囲気的には以下のような感じです。}}上記のプログラムを実行してボタンを押すと以下のような出力になります。Finished実際にどういう挙動になっているのか、まずはExecuteCoroutine関数から見ていきましょう。CoroutineScope(Dispatchers.Main);まず最初に、CoroutineScopeというものを準備しています。これはコルーチンの実行に関する面倒を見てくれるオブジェクトで、ここではメインスレッド(UIスレッド)から作成しています。Finished.")}CoroutineScope.launchからコルーチンを実行します。(実際にはMainスレッドのディスパッチャにコルーチンの実行をキューします)ここでラムダ式を与えていますが、これ自体が中断関数と呼ばれる特殊な関数になっています。中断関数からはsuspend修飾子のついた関数を呼び出すことができます。(それの何がいいかは後述。Completed")が実行されます。ExecuteCoroutine関数を抜けると、onCreate関数内の残りの処理が実行された後に、AndroidシステムへとUIスレッドの制御が返されます。すると、先ほどキューした中断関数(ラムダ式)がAndroidシステムによって実行されます。SampleCoroutine関数(これもsuspend修飾子がついている中断関数です)が呼び出されます。開始のログを出力したら、コルーチンを実際に中断します。continuation}suspendCoroutine<T>関数は、コルーチンを中断する関数です。これは、suspend修飾子のついた中断関数からのみ呼び出すことができます。suspendCoroutineは、与えられたラムダ式の中身を実行すると制御をAndroidシステムに返してしまいます。Continuation<Unit>です。これは、suspendCoroutineによって実行が先送りにされてしまった「後続の処理」そのものを表すオブジェクトです。このオブジェクトを操作すると、後続の処理を任意のタイミングで実行することができます。実際に実行しているのはbuttonのonClickListner内です。currentContinuation?.resume(Unit)}Continuation<T>.resume(T)は、Continuationで表現される処理の実行を再開します。Waited")が実行されます。Finished.")が実行されます。このように、KotlinのCoroutinesを使うと、関数を中断してContinuationを取り出し、任意のタイミングで再開することができます。(ちなみに、「継続」というのはれっきとしたプログラミング用語なので、気になる方はぜひ調べてみてください)プロジェクトの設定Coroutinesを実際にAndroidStudioプロジェクトで利用するには、いくつかの設定を済ませる必要があります。build.gradle(Project)Kotlinのバージョンを1.3以上にする必要があります。"1.3.21"としておきます。build.gradle(Module:app)CoroutinesのAndroid向けサポートを追加します。(先程の例で見たとおり、コルーチンを正常に動作させるにはAndroidシステムによるサポートが必要不可欠なのです。"org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1"}上記を書き換えたら、GradleでSyncを行います。UsbManager.requestPermissionをcoroutinesで処理するざざっと書いてみます。}}やっていることはさっきとだいたい同じなのでソースを良く読んでみてください。あとは、UIから抜けたとき(onClear)などのときにコルーチンをキャンセルする処理などがあったほうがいいかもしれません。コメントをキャンセルメールアドレスが公開されることはありません。