본문 바로가기

[Android Studio] USB Accessory 사용하기

by rudals.kim 2021. 1. 6. 댓글 개
반응형

안드로이드 USB에는 액세서리 모드라는 것이 있는데, 이를 사용하여 사용자는 Android 지원 기기용으로 특별히 설계된 USB 호스트 하드웨어를 연결할 수 있습니다.

 

어떤 식으로 사용할 수 있는지는 아래 게시글을 참고하시기 바랍니다.

아두이노에 USB Host Shield를 사용하여 안드로이드 폰과 연동시킬 수 있습니다.

 

[아두이노] USB HOST SHIELD 구매

아두이노에서 USB HOST 기능을 사용하기 위해 USB HOST SHIELD를 구매하였습니다. 아래와 같은 모양을 하고 있습니다. MAX3421(USB Peripheral/Host Controller with SPI Interface)을 사용하며 아두이노와 SPI로..

rudalskim.tistory.com

내 입맛에 맞는 안드로이드 어플리케이션을 제작해 보기로 했습니다.

제가 못찾는건지 아니면 많이 사용되지 않은 기능이라 예제가 정말 없네요.(아래 사이트를 참고하였습니다.)

 

USB 액세서리 개요  |  Android 개발자  |  Android Developers

USB 액세서리 모드를 통해 사용자는 Android 지원 기기용으로 특별히 설계된 USB 호스트 하드웨어를 연결할 수 있습니다. 액세서리는 Android 액세서리 개발 키트 문서에 개략적으로 설명된 Android 액

developer.android.com

액세서리 모드를 사용하기 위해 AndroidManifest.xml에 아래 feature/intent/meta-data를 추가합니다.

manifest tag에 아래 내용 추가
<uses-feature android:name="android.hardware.usb.accessory"/>

activity tag에 아래 내용 추가
<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"/>

 

 액서서리 권한 획득 

USB 액세서리와 통신하려면 애플리케이션에서 사용자로부터 권한을 받아야 합니다.

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);
        }
      }
    }
  }
};

 

 액서서리 연결 부분 

액세서리와 통신하기 위해 데이터를 읽고 쓸 수 있도록 usbManager로부터 입력 및 출력 스트림 얻어옵니다.

기본적인 송신은 outputStream으로 byte 데이터를 쓰면 되고, 수신은 inputStream으로부터 byte 데이터를 읽어 오면 됩니다.

주의하실 점은 수신은 UI 스레드가 block되지 않도록 별도의 쓰레드(아래 코드의 AccessoryThread)를 생성하여 동작시켜야 합니다.

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();
        }
    }

 

 액서서리 종료 부분 

액세서리와의 통신이 완료되었거나 액세서리가 분리되었다면 close()를 호출하여 열었던 파일 설명어를 닫습니다.

(예. 위의 inputStream, outputStream)

분리 이벤트를 수신 대기하려면 다음과 같이 broadcast receiver를 생성해야 합니다.

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
        }
      }
  }
};

 

 UI 구성 

간단하게 toggleButton 1개와 textView 2개로 구성해 보았습니다.

테스트용 폰에 설치를 해 봤습니다. 꺼짐/켜짐 버튼을 누르면 아두이노에 연결된 LED가 on/off를 합니다.

아래와 같은 식으로 외부 하드웨어를 사용하여 안드로이드 폰과 유선으로 통신할 수 있습니다.

요즘에는 동일한 기능을 저렴하게 무선으로 할 수 있어서 불편하게 유선이 사용되는 안드로이드 액세서리 모드가 사용될 일이 별로 없는 것 같습니다.

반응형

댓글