USB アクセサリの概要

USB アクセサリ モードでは、 Android デバイス専用に設計された USB ホスト ハードウェア。アクセサリは、 Android Accessory Development Kit のドキュメントに記載されている Android アクセサリ プロトコルに準拠させます。 これにより、USB ホストとして動作できない Android 搭載デバイスでも USB と通信できるようになります。 あります。Android 搭載デバイスが USB アクセサリ モードの場合、接続された Android USB ホストとして動作し、USB バスに電力を供給して、接続されたデバイスを列挙します。 Android 3.1(API レベル 12)は USB アクセサリ モードをサポートしており、この機能は Android 2.3.4(API レベル 10)では、より幅広いデバイスのサポートが可能になりました。

適切な USB アクセサリ API を選択する

USB アクセサリ API は、Android 3.1 でプラットフォームに導入されましたが、 Android 2.3.4 で利用できます。これらの API は 外部ライブラリを使用してバックポートする場合、USB をサポートするためにインポートできるパッケージが 2 つあります。 [アクセサリ モード] を選択します。どの Android 搭載デバイスをサポートするかに応じて、以下を行う必要があります。 次のように使用します。

  • com.android.future.usb: Android 2.3.4 で USB アクセサリ モードをサポートするには、 Google API アドオン ライブラリには、バックポート USB アクセサリ API が含まれています。これらの API は、 Namespace があります。Android 3.1 では、この名前空間内のクラスをインポートして呼び出すことも可能で、 サポートします。このアドオン ライブラリはシンラッパーです。 android.hardware.usb アクセサリ API に関する問題を解決しました。USB ホストモードはサポートされていません。条件 USB アクセサリ モードをサポートする幅広いデバイスをサポートしたい場合は、 このパッケージをインポートします。すべての Android 2.3.4 デバイスが USB アクセサリ機能をサポートするために必要です。個々のデバイス メーカーによって この機能をサポートするかどうかを指定するため、マニフェストで宣言する必要があります。 表示されます。
  • android.hardware.usb: この名前空間には、USB をサポートするクラスが含まれます Android 3.1 ではアクセサリ モードが導入されました。このパッケージはフレームワーク API の一部として組み込まれているため、 Android 3.1 は、アドオン ライブラリを使用しない USB アクセサリ モードをサポートしています。このパッケージを使用する USB のハードウェア サポートを備えた Android 3.1 以降のデバイスのみに関心がある場合 アクセサリ モードを使用できます。これはマニフェスト ファイルで宣言できます。

Google API アドオン ライブラリをインストールする

アドオンをインストールする場合は、Google API Android API 10 をインストールします。 SDK Manager で管理します。Google API のインストール アドオンをご覧ください。

API の概要

アドオン ライブラリはフレームワーク API のラッパーであるため、 USB アクセサリの機能は同様です。アドオン ライブラリを使用する場合でも、android.hardware.usb のリファレンス ドキュメントを使用できます。

注: ただし、 アドオン ライブラリとフレームワーク API の違いについて説明します。

USB アクセサリ API をサポートしているクラスを、次の表に示します。

クラス 説明
UsbManager 接続された USB デバイスの列挙と通信が可能です。
UsbAccessory USB アクセサリを表し、その識別情報にアクセスするためのメソッドを含んでいます。 情報です。

アドオン ライブラリとプラットフォーム API の使用方法の違い

Google API アドオン ライブラリを使用する場合とプラットフォームを使用する場合では、使用方法の 2 つの違いがあります。 API

アドオン ライブラリを使用している場合は、次の方法で UsbManager オブジェクトを取得する必要があります。

Kotlin

val manager = UsbManager.getInstance(this)

Java

UsbManager manager = UsbManager.getInstance(this);

アドオン ライブラリを使用していない場合は、次の方法で UsbManager オブジェクトを取得する必要があります。

Kotlin

val manager = getSystemService(Context.USB_SERVICE) as UsbManager

Java

UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);

インテント フィルタを使用して接続済みのアクセサリをフィルタする場合、UsbAccessory オブジェクトは、 説明します。アドオン ライブラリを使用している場合は、次の方法で UsbAccessory オブジェクトを取得する必要があります。

Kotlin

val accessory = UsbManager.getAccessory(intent)

Java

UsbAccessory accessory = UsbManager.getAccessory(intent);

アドオン ライブラリを使用していない場合は、次の方法で UsbAccessory オブジェクトを取得する必要があります。

Kotlin

val accessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY) as UsbAccessory

Java

UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);

Android マニフェストの要件

次のリストに、事前にアプリケーションのマニフェスト ファイルに追加する必要があるものを USB アクセサリの API を扱いますマニフェスト ファイルとリソース ファイル 例に、これらの項目を宣言する方法を示します。

  • すべての Android 搭載デバイスで USB アクセサリ API のサポートが保証されているわけではないため、 アプリが使用することを宣言する <uses-feature> 要素が含まれている android.hardware.usb.accessory 機能を使用します。
  • アドオン ライブラリ <uses-library> 要素を追加して ライブラリの com.android.future.usb.accessory
  • アドオン ライブラリを使用する場合は、アプリの最小 SDK を API レベル 10 に設定する android.hardware.usb パッケージを使用している場合は 12。
  • USB アクセサリが接続されたときにアプリケーションで通知されるようにするには、 次の要素の <intent-filter> 要素と <meta-data> 要素のペア android.hardware.usb.action.USB_ACCESSORY_ATTACHED インテントをメイン アクティビティで使用できます。 <meta-data> 要素は、外部 XML リソース ファイルをポイントします。 は、検出するアクセサリの識別情報を宣言します。

    XML リソース ファイルで、属性の <usb-accessory> 要素を宣言し、 フィルタするアクセサリを選択します各 <usb-accessory> には、 次のような属性があります。

    • manufacturer
    • model
    • version

    version でのフィルタリングはおすすめしません。アクセサリ デバイスでバージョン文字列が(意図的かどうかにかかわらず)指定されないことがあります。 アプリでフィルタするバージョン属性とアクセサリまたはデバイスを宣言する場合 バージョン文字列を指定しないと、NullPointerException がオンになります。 使用できます。この問題は Android 12 で修正されています。

    リソース ファイルを res/xml/ ディレクトリに保存します。リソース ファイル名 (.xml 拡張子なし)は、 <meta-data> 要素。XML リソース ファイルの形式も、 下記のをご覧ください。

マニフェストとリソース ファイルの例

マニフェストと、対応するリソース ファイルの例を次に示します。

<manifest ...>
    <uses-feature android:name="android.hardware.usb.accessory" />
    
    <uses-sdk android:minSdkVersion="<version>" />
    ...
    <application>
      <uses-library android:name="com.android.future.usb.accessory" />
        <activity ...>
            ...
            <intent-filter>
                <action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
            </intent-filter>

            <meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
                android:resource="@xml/accessory_filter" />
        </activity>
    </application>
</manifest>

この場合、次のリソース ファイルを res/xml/accessory_filter.xml であり、 対応するモデル、メーカー、バージョンはフィルタする必要があります。アクセサリから送信される Android 搭載デバイスに帰属します。

<?xml version="1.0" encoding="utf-8"?>

<resources>
    <usb-accessory model="DemoKit" manufacturer="Google" version="1.0"/>
</resources>

アクセサリと連携する

Android 搭載デバイスに USB アクセサリを接続すると、Android システムが次の処理を行います。 アプリが、接続されたアクセサリに関心があるかどうかを判断します。その場合は、 アクセサリとの通信を開始できます。そのためには、アプリで次の処理を行う必要があります。

  1. アクセサリをフィルタするインテント フィルタを使用して、コネクテッド アクセサリを検出する 接続されたアクセサリを列挙して適切なアクセサリを見つけます。
  2. お客様にアクセサリとの通信を許可するよう求める(まだ許可していない場合) 取得します。
  3. 適切なインターフェースでデータの読み書きを行い、アクセサリと通信する 提供します

アクセサリを検出する

アプリがアクセサリを検出するには、インテント フィルタを使用して、 ユーザーがアクセサリを接続したり、すでに接続されているアクセサリを列挙したりしたとき。使用 インテント フィルタは、新しいインテントをアプリケーションで アクセサリを選択します。接続されているアクセサリを列挙すると、すべてのアクセサリのリストを取得できます。 接続されているアクセサリや、アプリでインテントによるフィルタが行われていない場合に、この警告が表示されます。

インテント フィルタを使用する

アプリが特定の USB アクセサリを検出するには、インテント フィルタを指定します。 android.hardware.usb.action.USB_ACCESSORY_ATTACHED インテントでフィルタします。そろそろ このインテント フィルタでは、USB のプロパティを指定するリソース ファイルを指定する必要があります。 アクセサリ(メーカー、モデル、バージョンなど)を記録します。

インテント フィルタを宣言する方法の例を次に示します。

<activity ...>
    ...
    <intent-filter>
        <action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
    </intent-filter>

    <meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
        android:resource="@xml/accessory_filter" />
</activity>

次の例は、対応するリソース ファイルを宣言する方法を示しています。 関心のある USB アクセサリ:

<?xml version="1.0" encoding="utf-8"?>

<resources>
    <usb-accessory manufacturer="Google, Inc." model="DemoKit" version="1.0" />
</resources>

アクティビティでは、以下を表す UsbAccessory を取得できます。 アタッチされたアクセサリを、次のようにインテントから(アドオン ライブラリを使用して)取得します。

Kotlin

val accessory = UsbManager.getAccessory(intent)

Java

UsbAccessory accessory = UsbManager.getAccessory(intent);

プラットフォーム API を使用する場合は次のようになります。

Kotlin

val accessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY) as UsbAccessory

Java

UsbAccessory accessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);

アクセサリを列挙する

識別されたアクセサリをアプリケーションで列挙して、 表示されます。

getAccessoryList() メソッドを使用する 接続されているすべての USB アクセサリの配列を取得できます。

Kotlin

val manager = getSystemService(Context.USB_SERVICE) as UsbManager
val accessoryList: Array<out UsbAccessory> = manager.accessoryList

Java

UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
UsbAccessory[] accessoryList = manager.getAccessoryList();

注: できます。

アクセサリとの通信の権限を取得する

USB アクセサリと通信するには、事前に できます。

注: アプリケーションで インテント フィルタを使用して、接続されたアクセサリを検出すると、 ユーザーがアプリにインテントの処理を許可した場合に、権限を取得する必要があります。使用していない場合は、 アクセサリに接続する前に、アプリで明示的に許可する必要があります。

明示的な許可を求めることは、 アプリケーションは、すでに接続されていて通信が必要なアクセサリを列挙します。 1 です。アクセサリと通信する前に、アクセサリへのアクセス権限を確認する必要があります。 そうしないと、ユーザーがファイルへのアクセスを拒否した場合、ランタイム エラーが発生します。 含まれます。

明示的に権限を取得するには、まずブロードキャスト レシーバを作成します。このレシーバは requestPermission() を呼び出したときにブロードキャストされるインテントです。requestPermission() を呼び出すと、ダイアログが表示され、 アクセサリへの接続許可を求めるメッセージがユーザーに表示されます。次のサンプルコードは、 ブロードキャスト レシーバを作成します。

Kotlin

private const val ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION"

private val usbReceiver = object : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        if (ACTION_USB_PERMISSION == intent.action) {
            synchronized(this) {
                val accessory: UsbAccessory? = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY)

                if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                    accessory?.apply {
                        // call method to set up accessory communication
                    }
                } else {
                    Log.d(TAG, "permission denied for accessory $accessory")
                }
            }
        }
    }
}

Java

private static final String ACTION_USB_PERMISSION =
    "com.android.example.USB_PERMISSION";
private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {

    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (ACTION_USB_PERMISSION.equals(action)) {
            synchronized (this) {
                UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);

                if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                    if(accessory != null){
                        // call method to set up accessory communication
                    }
                }
                else {
                    Log.d(TAG, "permission denied for accessory " + accessory);
                }
            }
        }
    }
};

ブロードキャスト レシーバを登録するには、これを onCreate() メソッドの アクティビティ:

Kotlin

private const val ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION"
...
val manager = getSystemService(Context.USB_SERVICE) as UsbManager
...
permissionIntent = PendingIntent.getBroadcast(this, 0, Intent(ACTION_USB_PERMISSION), 0)
val filter = IntentFilter(ACTION_USB_PERMISSION)
registerReceiver(usbReceiver, filter)

Java

UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
private static final String ACTION_USB_PERMISSION =
    "com.android.example.USB_PERMISSION";
...
permissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(usbReceiver, filter);

アクセサリへの接続の許可を求めるダイアログを表示するには、 requestPermission() メソッド:

Kotlin

lateinit var accessory: UsbAccessory
...
usbManager.requestPermission(accessory, permissionIntent)

Java

UsbAccessory accessory;
...
usbManager.requestPermission(accessory, permissionIntent);

ユーザーがダイアログに返信すると、ブロードキャスト レシーバは EXTRA_PERMISSION_GRANTED エクストラ(ブール値) 回答を表現します。接続する前に、このエクストラ値が true であるかどうかを 含まれます。

アクセサリと通信する

アクセサリと通信するには、UsbManager を使用します。 データの読み取り / 書き込み用の入力ストリームと出力ストリームを設定できるファイル記述子を取得します。 使用します。ストリームは、アクセサリの入出力用バルク エンドポイントを表します。次のように設定します。 デバイスとアクセサリ間の通信を別のスレッドで開始し、 呼び出すことができます通信するアクセサリを開く方法を次の例に示します。

Kotlin

private lateinit var accessory: UsbAccessory
private var fileDescriptor: ParcelFileDescriptor? = null
private var inputStream: FileInputStream? = null
private var outputStream: FileOutputStream? = null
...

private fun openAccessory() {
    Log.d(TAG, "openAccessory: $mAccessory")
    fileDescriptor = usbManager.openAccessory(accessory)
    fileDescriptor?.fileDescriptor?.also { fd ->
        inputStream = FileInputStream(fd)
        outputStream = FileOutputStream(fd)
        val thread = Thread(null, this, "AccessoryThread")
        thread.start()
    }
}

Java

UsbAccessory accessory;
ParcelFileDescriptor fileDescriptor;
FileInputStream inputStream;
FileOutputStream outputStream;
...

private void openAccessory() {
    Log.d(TAG, "openAccessory: " + accessory);
    fileDescriptor = usbManager.openAccessory(accessory);
    if (fileDescriptor != null) {
        FileDescriptor fd = fileDescriptor.getFileDescriptor();
        inputStream = new FileInputStream(fd);
        outputStream = new FileOutputStream(fd);
        Thread thread = new Thread(null, this, "AccessoryThread");
        thread.start();
    }
}

スレッドの run() メソッドで、アクセサリに対する読み取りと書き込みを行うには、 FileInputStream オブジェクトまたは FileOutputStream オブジェクト。読むとき FileInputStream オブジェクトを使用してアクセサリからのデータを取得する場合、 USB パケットデータを保存するのに十分な容量です。Android アクセサリ プロトコルは、 最大 16,384 バイトです。したがって、バッファが 16,384 バイト以下であることを シンプルにしました。

注: USB の場合、下位レベルでのパケットは 64 バイトです。 USB 高速アクセサリの場合は 512 バイトです。Android アクセサリ プロトコルは、簡略化するために、両方の速度のパケットを 1 つの論理パケットにバンドルします。

Android でのスレッドの使用について詳しくは、プロセスと スレッドをご覧ください。

アクセサリとの通信を終了する

アクセサリとの通信を完了したら、またはアクセサリが取り外された場合は、 close() を呼び出して開いたファイル記述子です。 接続解除のイベントをリッスンするには、次のようにしてブロードキャスト レシーバを作成します。

Kotlin

var usbReceiver: BroadcastReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {

        if (UsbManager.ACTION_USB_ACCESSORY_DETACHED == intent.action) {
            val accessory: UsbAccessory? = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY)
            accessory?.apply {
                // call your method that cleans up and closes communication with the accessory
            }
        }
    }
}

Java

BroadcastReceiver usbReceiver = new BroadcastReceiver() {
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();

        if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
            UsbAccessory accessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
            if (accessory != null) {
                // call your method that cleans up and closes communication with the accessory
            }
        }
    }
};

マニフェストではなくアプリ内にブロードキャスト レシーバを作成すると、 切断されたイベントのみを処理するようにできます。これにより、分離されたイベントは すべてのアプリケーションにブロードキャストするのではなく、現在実行中のアプリケーションにのみ送信する場合。