USB ana makinesine genel bakış

Android destekli cihazınız USB ana makine modundayken USB ana makinesi olarak çalışır, veri yolu ve bağlı USB cihazlarını sıralar. USB ana makine modu, Android 3.1 ve sonraki sürümlerde desteklenir.

API'ye Genel Bakış

Başlamadan önce, hangi sınıflar üzerinde çalışmanız gerektiğini anlamanız önemlidir. İlgili içeriği oluşturmak için kullanılan Aşağıdaki tabloda android.hardware.usb paketindeki USB ana makine API'leri açıklanmaktadır.

Tablo 1. USB Ana Makine API'leri

Sınıf Açıklama
UsbManager Bağlı USB cihazlarını numaralandırmanıza ve bu cihazlarla iletişim kurmanıza olanak tanır.
UsbDevice Bağlı bir USB cihazını temsil eder ve tanımlamaya yönelik yöntemler içerir bilgi, arayüzler ve uç noktalar.
UsbInterface Bir USB cihazı arayüzünü temsil eder ve bu arayüz, olanak tanır. Bir cihazın iletişim kurulacak bir veya daha fazla arayüzü olabilir.
UsbEndpoint Bu arayüz için bir iletişim kanalı olan arayüz uç noktasını temsil eder. arayüz bir veya daha fazla uç noktaya sahip olabilir ve genellikle iki yönlü iletişim kurulmasını sağlar.
UsbDeviceConnection Uç noktalarda veri aktaran cihaz bağlantısını temsil eder. Bu sınıf verileri eşzamanlı veya eşzamansız olarak karşılıklı olarak göndermenize olanak tanır.
UsbRequest UsbDeviceConnection aracılığıyla bir cihazla iletişim kurmak için eşzamansız bir isteği temsil eder.
UsbConstants Linux'un linux/usb/ch9.h'deki tanımlara karşılık gelen USB sabit değerlerini tanımlar kernel'e gidin.

Çoğu durumda, bu sınıfların tümünü kullanmanız gerekir (UsbRequest yalnızca eşzamansız iletişim gerçekleştiriyorsanız gereklidir) iletişim sırasında yürütülür. Genel olarak, istenen UsbDevice öğesini almak için bir UsbManager alırsınız. Cihaz yanınızda olduğunda uygun UsbInterface ve UsbEndpoint'nı bulmanız gerekir bir iletişim arayüzü seçin. Doğru uç noktayı aldıktan sonra, USB cihazıyla iletişim kurmak için bir UsbDeviceConnection açın.

Android manifesti şartları

Aşağıdaki listede, Google Haritalar'dan ayrılmadan önce uygulamanızın manifest dosyasına eklemeniz gereken bilgileri bulabilirsiniz USB ana makine API'larıyla çalışma:

  • Android destekli tüm cihazların USB ana makine API'lerini desteklediği garanti edilmediğinden, uygulamanızın<uses-feature> android.hardware.usb.host özelliği.
  • Uygulamanın minimum SDK sürümünü API Düzeyi 12 veya sonraki bir sürüme ayarlayın. USB ana makine API'leri önceki API düzeylerinde mevcuttur.
  • Takılı bir USB cihazıyla ilgili olarak uygulamanıza bildirim gönderilmesini istiyorsanız bir Şu için <intent-filter> ve <meta-data> öğe çifti: Ana etkinliğinizde android.hardware.usb.action.USB_DEVICE_ATTACHED intent. İlgili içeriği oluşturmak için kullanılan <meta-data> öğesi, aşağıdakileri bildiren harici bir XML kaynak dosyasına işaret ediyor: algılamak istediğiniz cihazla ilgili tanımlayıcı bilgiler.

    XML kaynak dosyasında USB için <usb-device> öğelerini tanımlayın cihazları seçin. Aşağıdaki listede <usb-device> Genel olarak, filtre uygulayarak bir filtre oluşturmak için ve bir grup için filtre uygulamak istiyorsanız sınıf, alt sınıf ve protokolü kullanın. depolama cihazları ve dijital kameralar gibi USB cihazlarıyla çalışır. Herhangi bir özellikler. Her USB cihazla eşleşen özellik belirtmemenizi sağlar; bu nedenle bunu yalnızca yapın. uygulamanız gerekiyorsa:

    • vendor-id
    • product-id
    • class
    • subclass
    • protocol (cihaz veya arayüz)

    Kaynak dosyayı res/xml/ dizinine kaydedin. Kaynak dosya adı (.xml uzantısı olmayan) şu adreste belirttiğinizle aynı olmalıdır: <meta-data> öğesi. XML kaynak dosyasının biçimi example bakın.

Manifest ve kaynak dosyası örnekleri

Aşağıdaki örnekte örnek bir manifest ve karşılık gelen kaynak dosyası gösterilmektedir:

<manifest ...>
    <uses-feature android:name="android.hardware.usb.host" />
    <uses-sdk android:minSdkVersion="12" />
    ...
    <application>
        <activity ...>
            ...
            <intent-filter>
                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
            </intent-filter>

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

Bu durumda, aşağıdaki kaynak dosya res/xml/device_filter.xml ve belirtilen özelliklerine filtre uygulanması gerekir:

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

<resources>
    <usb-device vendor-id="1234" product-id="5678" class="255" subclass="66" protocol="1" />
</resources>

Cihazlarla çalışma

Kullanıcılar USB cihazları Android destekli bir cihaza bağladığında Android sistemi, uygulamanızın bağlı cihazla ilgilenip ilgilenmediğini görebilirsiniz. Öyleyse, hesap erişimini iletişim kurmalarına izin verilmez. Bunun için uygulamanız:

  1. Kullanıcı aşağıdaki işlemleri gerçekleştirdiğinde bildirim almak için intent filtresi kullanarak bağlı USB cihazları keşfedin bir USB cihazına bağlanarak veya zaten bağlı olan USB cihazlarını numaralandırarak.
  2. Henüz almadıysanız, kullanıcıdan USB cihazına bağlanma izni isteyin.
  3. Uygun arayüzde veri okuyup yazarak USB cihazıyla iletişim kurun. uç noktalar.

Bir cihazı keşfedin

Uygulamanız, şu durumlarda bildirim almak için bir intent filtresi kullanarak USB cihazları keşfedebilir: Kullanıcı bir cihazı bağlayarak veya zaten bağlı olan USB cihazlarını numaralandırarak. Bir intent filtresi, uygulamanızın bir anahtar kelimeyi otomatik olarak tercih edebilirsiniz. Tüm bağlı USB cihazlarının listesini almak isterseniz, bu cihazların sıralanması amaçlar için filtre uygulamamış olabilir.

Amaç filtresi kullanın

Uygulamanızın belirli bir USB cihazını bulmasına yardımcı olmak için bir intent filtresi android.hardware.usb.action.USB_DEVICE_ATTACHED amacı için filtre uygulayın. Şununla birlikte: USB özelliklerini belirten bir kaynak dosyası belirtmeniz gerekir kimlik bilgilerini (ör. ürün ve tedarikçi kimliği) girin. Kullanıcılar, cihazınızla eşleşen bir cihaz bağladığında filtresini uyguladığınızda sistem, bu kullanıcılara uygulamanızı başlatmak isteyip istemediklerini soran bir iletişim kutusu gösterir. Kullanıcılar kabul ederse uygulamanızın, şu tarihe kadar cihaza otomatik olarak erişim izni olur: cihazın bağlantısı kesildi.

Aşağıdaki örnekte intent filtresinin nasıl bildirileceği gösterilmektedir:

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

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

Aşağıdaki örnekte İlgilendiğiniz USB cihazları:

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

<resources>
    <usb-device vendor-id="1234" product-id="5678" />
</resources>

Etkinliğinizde, alan adını temsil eden UsbDevice ekli cihazı şu şekilde niyetten kaldırın:

Kotlin

val device: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)

Java

UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

Cihazları numaralandırma

Uygulamanız şu anda bağlı olan tüm USB cihazlarını incelemek istiyorsa uygulamanız çalışırken veri yolundaki cihazları sıralayabilir. Tüm karma haritalarını almak için getDeviceList() yöntemini kullanın bağlı olan USB cihazlarıdır. İsterseniz karma eşleme, USB cihazının adıyla anahtarlanır. haritadan bir cihaz edinin.

Kotlin

val manager = getSystemService(Context.USB_SERVICE) as UsbManager
...
val deviceList = manager.getDeviceList()
val device = deviceList.get("deviceName")

Java

UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
...
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
UsbDevice device = deviceList.get("deviceName");

Dilerseniz karma haritasından bir iteratör alıp her cihaz için bir iterasyon yapabilirsiniz. tek tek:

Kotlin

val manager = getSystemService(Context.USB_SERVICE) as UsbManager
..
val deviceList: HashMap<String, UsbDevice> = manager.deviceList
deviceList.values.forEach { device ->
    // your code
}

Java

UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
...
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while(deviceIterator.hasNext()){
    UsbDevice device = deviceIterator.next();
    // your code
}

Bir cihazla iletişim kurma izni alma

USB cihazıyla iletişim kurmadan önce, uygulamanızın, yardımcı olur.

Not: Uygulamanız bir intent filtresine dokunun. Bu filtre, bağlı oldukları USB cihazları otomatik olarak alır. izni gerekir. Aksi halde, ve cihaza bağlanmadan önce bu izni uygulamanızda açıkça belirtin.

Açıkça izin istemeniz bazı durumlarda (ör. uygulama zaten bağlı olan ve ardından iletişim kurmak isteyen USB cihazlarını numaralandırır bir. Bir cihazla iletişim kurmayı denemeden önce cihaza erişim iznini kontrol etmeniz gerekir. Eğer Kullanıcı, cihaza erişim izni vermeyi reddettiğinde çalışma zamanı hatası alırsınız.

Açıkça izin almak için önce bir yayın alıcı oluşturun. Bu alıcı şunları dinliyor: requestPermission() adlı kişiyi aradığınızda anons edilen niyeti gösterir. requestPermission() çağrısı, kullanıcıya bağlanma izni istiyor. Aşağıdaki örnek kod, yayın alıcısını oluşturun:

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 device: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)

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

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) {
                UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

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

Yayın alıcıyı kaydetmek için bunu uygulamanızdaki onCreate() yönteminize ekleyin. etkinlik:

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), PendingIntent.FLAG_IMMUTABLE)
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), PendingIntent.FLAG_IMMUTABLE);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(usbReceiver, filter);

Cihaza bağlanmak için kullanıcılardan izin isteyen iletişim kutusunu görüntülemek için requestPermission() yöntemini çağırın:

Kotlin

lateinit var device: UsbDevice
...
usbManager.requestPermission(device, permissionIntent)

Java

UsbDevice device;
...
usbManager.requestPermission(device, permissionIntent);

Kullanıcılar iletişim kutusuna yanıt verdiğinde yayın alıcınız EXTRA_PERMISSION_GRANTED ekstra (bir boole değeri) temsil eder. olanak tanır.

Bir cihazla iletişim kurma

Bir USB cihazıyla iletişim eşzamanlı veya eşzamansız olabilir. Her iki durumda da, tüm veri aktarımlarını gerçekleştirecek yeni bir iş parçacığı oluşturmanız gerekir, böylece Kullanıcı arayüzü iş parçacığı. Bir cihazla iletişimi doğru bir şekilde kurmak için uygun UsbInterface ve UsbEndpoint ve bu uç noktada bir UsbDeviceConnection ile istek göndermek istediğiniz bir cihaz bulun. Genel olarak, kodunuz:

  • UsbDevice nesnesinin özelliklerini (ör. ürün kimliği) kontrol edin aracılığıyla iletişim kurmak isteyip istemediğinizi belirlemek için Tedarikçi Firma kimliğini veya cihaz sınıfını olanak tanır.
  • Cihazla iletişim kurmak istediğinizden emin olduğunuzda uygun UsbInterface ile birlikte iletişim kurmak için kullanmak istediğiniz söz konusu arayüze ait uygun UsbEndpoint. Arayüzlerde bir olabilir daha fazla uç noktaya sahiptir ve genellikle iki yönlü için bir giriş ve çıkış uç noktasına iyi bir iletişimdir.
  • Doğru uç noktayı bulduğunuzda bir UsbDeviceConnection açın görebilirsiniz.
  • Uç noktada iletmek istediğiniz verileri bulkTransfer() veya controlTransfer() yöntemiyle sağlayın. Şunları yapmalısınız: Ana kullanıcı arayüzü iş parçacığının engellenmesini önlemek için bu adımı başka bir iş parçacığında uygulayın. Daha fazla hakkında daha fazla bilgi için İşlemler ve İleti dizileri.

Aşağıdaki kod snippet'i, eşzamanlı veri aktarımı yapmanın basit bir yoludur. Kodunuz doğru arayüzü ve iletişim noktalarını bulmak için daha fazla mantığa Ayrıca, veri aktarımlarını ana kullanıcı arayüzü iş parçacığından farklı bir iş parçacığında yapmalıdır:

Kotlin

private lateinit var bytes: ByteArray
private val TIMEOUT = 0
private val forceClaim = true

...

device?.getInterface(0)?.also { intf ->
    intf.getEndpoint(0)?.also { endpoint ->
        usbManager.openDevice(device)?.apply {
            claimInterface(intf, forceClaim)
            bulkTransfer(endpoint, bytes, bytes.size, TIMEOUT) //do in another thread
        }
    }
}

Java

private Byte[] bytes;
private static int TIMEOUT = 0;
private boolean forceClaim = true;

...

UsbInterface intf = device.getInterface(0);
UsbEndpoint endpoint = intf.getEndpoint(0);
UsbDeviceConnection connection = usbManager.openDevice(device);
connection.claimInterface(intf, forceClaim);
connection.bulkTransfer(endpoint, bytes, bytes.length, TIMEOUT); //do in another thread

Eşzamansız olarak veri göndermek için initialize için UsbRequest sınıfını ve eşzamansız bir isteği queue kullanın, ardından sonucu bekleyin requestWait() ile.

Cihazla iletişimi sonlandırma

Bir cihazla iletişimi bitirdiğinizde veya cihaz çıkarıldıysa UsbInterface ve UsbDeviceConnection şunları kapatın: releaseInterface() ve close(). Ayrılan etkinlikleri dinlemek için: aşağıdaki gibi bir yayın alıcı oluşturun:

Kotlin

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

        if (UsbManager.ACTION_USB_DEVICE_DETACHED == intent.action) {
            val device: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)
            device?.apply {
                // call your method that cleans up and closes communication with the device
            }
        }
    }
}

Java

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

      if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
            UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
            if (device != null) {
                // call your method that cleans up and closes communication with the device
            }
        }
    }
};

Manifest yerine uygulama içinde yayın alıcısını oluşturmak yalnızca çalışma sırasında özel etkinlik yönetimi Bu şekilde, ayrılmış etkinlikler yalnızca o anda çalışan ve tüm uygulamalara yayınlanmayan uygulamaya gönderilir.