최근 안드로이드 단말에 USB 연결 상태를 확인하기 위해서 이곳저곳 찾다가 보니..
구글 오픈소스에 등록되어있는 UsbManager 클래스를 알게 되었습니다.
해당 클래스는 USB 상태에 접근하고 USB 장치와 통신을 위한 클래스라고 합니다.
이번 글에서는 UsbManager 클래스를 참조하여 USB 연결상태 뿐만 아니라
다양한 USB 상태를 가져오는 방법을 정리하려고 합니다.
1. USB 상태 관리 클래스 : UsbStateManager
USB 상태를 확인하기 위한 UsbStateManager Class 를 작성합니다.
해당 클래스의 주요 내용은 세가지 입니다.
- USB 상태 브로드캐스트 리시버 등록을 위한 register/unregister 메서드 (동적 생성)
- USB 상태를 수신받는 Receiver
- USB 상태는 map 에 저장하여 콜백함수 호출
class UsbStateManager(private val context: Context) {
private val usbStateMap = HashMap<String, Boolean>()
private var callback: OnUsbStateListener? = null
private val receiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val action = intent.action
try {
if (action == ACTION_USB_STATE) { // USB 상태 수신!!
intent.extras?.run {
usbStateMap[USB_CONNECTED] = getBoolean(USB_CONNECTED)
usbStateMap[USB_HOST_CONNECTED] = getBoolean(USB_HOST_CONNECTED)
usbStateMap[USB_CONFIGURED] = getBoolean(USB_CONFIGURED)
usbStateMap[USB_FUNCTION_ADB] = getBoolean(USB_FUNCTION_ADB)
usbStateMap[USB_FUNCTION_RNDIS] = getBoolean(USB_FUNCTION_RNDIS)
usbStateMap[USB_FUNCTION_MTP] = getBoolean(USB_FUNCTION_MTP)
usbStateMap[USB_FUNCTION_PTP] = getBoolean(USB_FUNCTION_PTP)
usbStateMap[USB_FUNCTION_AUDIO_SOURCE] = getBoolean(USB_FUNCTION_AUDIO_SOURCE)
usbStateMap[USB_FUNCTION_MIDI] = getBoolean(USB_FUNCTION_MIDI)
usbStateMap[USB_FUNCTION_ACCESSORY] = getBoolean(USB_FUNCTION_ACCESSORY)
usbStateMap[USB_FUNCTION_NCM] = getBoolean(USB_FUNCTION_NCM)
callback?.onStateChanged(usbStateMap)
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
fun register(listener: OnUsbStateListener) {
callback = listener
val intentFilter = IntentFilter()
intentFilter.addAction(ACTION_USB_STATE)
context.registerReceiver(receiver, intentFilter)
}
fun unregister() {
try {
context.unregisterReceiver(receiver)
} catch (e: Exception) {
e.printStackTrace()
}
}
interface OnUsbStateListener {
fun onStateChanged(map: HashMap<String, Boolean>)
}
companion object {
/**
* USB 관련 Broadcast Actions
*
* ACTION_USB_STATE : USB 상태 수신을 위한 고정 Broadcast Action
*/
const val ACTION_USB_STATE = "android.hardware.usb.action.USB_STATE"
/**
* USB 상태 수신 extras
*
* USB_CONNECTED : USB 연결 상태
* USB_HOST_CONNECTED : USB 호스트로 연결 상태
* USB_CONFIGURED : USB 연결 시 구성이 완료되었는지 여부
*
* USB_FUNCTION_ADB : USB 디버깅 기능 활성화 여부
* USB_FUNCTION_MTP : 파일 전송 기능 활성화 여부
* USB_FUNCTION_RNDIS : USB 테더링 기능 활성화 여부
* USB_FUNCTION_MIDI : 악기와 연결하여 사용하는 기능 활성화 여부
* USB_FUNCTION_PTP : 이미지 전송 기능 활성화 여부
*
* USB_FUNCTION_AUDIO_SOURCE : 오디오 기능 활성화 여부
* USB_FUNCTION_ACCESSORY : 액세서리 모드 기능 활성화 여부
* USB_FUNCTION_NCM : 공장 OS 기능 활성화 여부
*/
const val USB_CONNECTED = "connected"
const val USB_HOST_CONNECTED = "host_connected"
const val USB_CONFIGURED = "configured"
const val USB_FUNCTION_ADB = "adb"
const val USB_FUNCTION_MTP = "mtp"
const val USB_FUNCTION_RNDIS = "rndis"
const val USB_FUNCTION_MIDI = "midi"
const val USB_FUNCTION_PTP = "ptp"
const val USB_FUNCTION_AUDIO_SOURCE = "audio_source"
const val USB_FUNCTION_ACCESSORY = "accessory"
const val USB_FUNCTION_NCM = "ncm"
}
}
2. USB 상태
Receiver를 통해 수신한 USB 상태 값들은 각각 어떤 의미를 가지는지 간략하게 살펴보겠습니다.
(아래 서술하는 상태 값은 Boolean 타입을 가진다.)
USB_CONNECTED
USB 연결 상태
일반적으로 단말과 장비의 연결 상태를 나타낸다.
USB_HOST_CONNECTED
USB 호스트로 연결 상태
단말이 호스트로 연결된 상태를 나타낸다.
대표적으로 단말에 이어폰(C-Type)을 연결했을 때 단말이 호스트로 연결된다.
USB_CONFIGURED
USB 연결 시 구성이 완료되었는지 여부
USB_FUNCTION_ADB
ADB : Android Debug Bridge, USB 디버깅 기능
개발자 옵션에서 "USB 디버깅" 상태 값을 나타낸다.
USB_FUNCTION_MTP
MTP : Media Transfer Protocol, 파일 전송 기능USB 설정에서 "파일 전송" 상태 값을 나타낸다.
USB_FUNCTION_RNDIS
RNDIS : Remote NDIS, USB 테더링 기능
USB 설정에서 "USB 테더링" 상태 값을 나타낸다.
USB_FUNCTION_MIDI
MIDI : Musical Instrument Digital Interface, 피아노와 같은 악기와 연결하여 사용하는 기능
USB 설정에서 "MIDI" 상태 값을 나타낸다.
USB_FUNCTION_PTP
PTP : Photo Transfer Protocol, 이미지 전송 기능USB 설정에서 "이미지 전송" 상태 값을 나타낸다.
3. USB 상태 결과보기
USB 상태를 가져올 준비는 끝났으니 결과를 직접 확인해보려고 합니다.
MainActivity에서 usbStateManager register 메서드를 호출해서 USB 상태를 표시해 주도록 했습니다.
class MainActivity : AppCompatActivity() {
lateinit var binding: ActivityMainBinding
private var usbStateManager: UsbStateManager? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
usbStateManager = UsbStateManager(this)
usbStateManager?.register(object : UsbStateManager.OnUsbStateListener {
override fun onStateChanged(map: HashMap<String, Boolean>) {
binding.tvConnected.text = map[UsbStateManager.USB_CONNECTED].toString()
binding.tvHostConnected.text = map[UsbStateManager.USB_HOST_CONNECTED].toString()
binding.tvConfigured.text = map[UsbStateManager.USB_CONFIGURED].toString()
binding.tvFunctionAdb.text = map[UsbStateManager.USB_FUNCTION_ADB].toString()
binding.tvFunctionMtp.text = map[UsbStateManager.USB_FUNCTION_MTP].toString()
binding.tvFunctionRndis.text = map[UsbStateManager.USB_FUNCTION_RNDIS].toString()
binding.tvFunctionMidi.text = map[UsbStateManager.USB_FUNCTION_MIDI].toString()
binding.tvFunctionPtp.text = map[UsbStateManager.USB_FUNCTION_PTP].toString()
binding.tvFunctionAudioSource.text = map[UsbStateManager.USB_FUNCTION_AUDIO_SOURCE].toString()
binding.tvFunctionAccessory.text = map[UsbStateManager.USB_FUNCTION_ACCESSORY].toString()
binding.tvFunctionNcm.text = map[UsbStateManager.USB_FUNCTION_NCM].toString()
}
})
}
override fun onDestroy() {
super.onDestroy()
usbStateManager?.unregister()
}
}
PC와 단말을 연결하고 USB 설정이 파일전송(MTP)인 경우
표시되는 결과를 아래와 같이 확인할 수 있었습니다.
4. 예제 다운로드
전체 소스코드는 아래 링크에서 확인 가능합니다.
https://github.com/bictoselfdev/UsbStateManager
[Reference]
0 comments: