일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 테스트 자동화
- SWIFTUI
- MotionLayout
- Kotlin
- node
- android13
- 인앱결제
- Reactive
- MediaSession
- 동영상
- Koin
- Observable
- google play
- GCP
- mysql
- list
- MediaPlayer
- liveData
- Android 13
- SwiftUI Tutorial
- PagingLib
- RxKotlin
- mvvm
- databinding
- Animation
- node.js
- junit
- paging
- Android
- rx
- Today
- Total
봄날은 갔다. 이제 그 정신으로 공부하자
android 다양한 주변장치 연동 (NFC, USB) 본문
안드로이드는 소스가 오픈되어 있기 때문에 많은 개발자 및 회사에서 안드로이드를 기반으로한 다양한 디바이스를 만들거나 안드로이드 장치와 연동이되는 주변 장치를 만들고 있습니다.
당장 온라인 마켓에 들어가 키오스크나 네비게이션을 검색해보아도 많은 회사들이 안드로이드 기반으로 제품을 생산한다는 것을 알 수 있습니다. 안드로이드를 더이상 핸드폰이나 타블렛에 탑재되는 OS로 한정하기는 곤란해보이는 상황 입니다.
각설하고
안드로이드 디바이스가 많이 출시되다보니 안드로이드에 연동되는 다양한 주변장치가 많아지고 있는데,
이 글에서는 안드로이드에서 NFC 카드와 USB 디바이스를 연동하는 방법에 대해 설명 합니다.
NFC 연동
Android는 기본적으로 NFC read / write 기능을 지원합니다.
해당 기능을 사용하기 위해서는 우선 아래와 같이 AndroidManifest.xml에 NFC 사용 권한을 선언해야 합니다.
<uses-permission android:name="android.permission.NFC" />
NFC는 projection Level이 NORMAL이므로 사용자로부터 별도의 승인을 받을 필요는 없습니다.
다만 해당 android DEVICE에서 NFC 기능을 지원하는지와 NFC 기능이 ON 되어 있는지 확인이 필요합니다.
확인하는 방법은 아래와 같습니다.
val nfcAdapter = NfcAdapter.getDefaultAdapter(this)
이 때 nfcAdapter가 null이면 해당 DEVICE는 NFC 기능을 지원하지 않는 DEVICE 입니다.
nfcAdapter의 isEnabled 값이 TRUE이면 ON이고 FALSE이면 OFF 상태 입니다.
FALSE인 경우, 팝업 등으로 사용자에게 NFC를 켜달라고 정중하게 요청하면 됩니다.
var intent = Intent()
intent.action = Settings.ACTION_NFC_SETTINGS
startActivity(intent)
이제 CARD를 인식했을 때 EVENT를 받을 activity를 지정합니다.
activity에서 이벤트를 받을 거니까, activity가 활성화되는 onResume() 함수에 아래 내용을 추가합니다.
val targetIntent = Intent(this, MyNfcActivity.class)
val pendingIntent = PendingIntent.getActivity(MyNfcActivity.this, 0, targetIntent, 0)
val ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED)
val tag = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED)
...
val filters = IntentFilter[] { ndef, tag, }
val techLists = String[][] { String[] {MyNfcActivity.class.getName() } }
nfcAdapter.enableForegroundDispatch(MyNfcActivity.this, pendingIntent, filters, techLists)
그리고 activity가 비활성화되면 NFC 이벤트를 받으면 안되니 onPause() 함수에 아래 내용을 추가합니다.
nfcAdapter.disableForegroundDispatch(MyNfcActivity.this)
여기까지하면 DEVICE에서 CRAD 인식시 onNewIntent() 함수로 인식된 카드 정보가 넘어 옵니다.
우리에게 필요한건 인식한 카드의 Serial Number이므로 아래와 같이 구현해 줍니다.
@Override
public void onNewIntent(Intent newIntent) {
super.onNewIntent(newIntent);
val tag : Tag? = newIntent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
if (tag == null) {
return
}
val serialNumber : ByteArray? = tag.getId())
}
이렇게 받아온 Serial Number는 Byte Array이므로 아래와 같은 함수를 만들어 가독성을 올려줍니다.
fun toHexString(buffer: ByteArray): String {
var bufferString = ""
for (i in buffer.indices) {
var hexChar = Integer.toHexString((buffer[i] and 0xFF.toByte()).toInt())
if (hexChar.length == 1) {
hexChar = "0$hexChar"
}
bufferString += hexChar.toUpperCase() + " "
}
return bufferString
}
CARD를 구분하기 위해서는 Serial Number 외에 추가로 CARD TYPE도 필요합니다.
CARD TYPE은 아래와 같이 Tag의 tech list를 통해 얻을 수 있습니다.
for(tag in tag.techList){
...
}
이렇게 얻어오는 정보는 아래와 같습니다.
[android.nfc.tech.NfcA, android.nfc.tech.MifareClassic, android.nfc.tech.NdefFormatable]
"android.nfc.tech.NfcA" 첫번째 이 내용 중 "NfcA" 인식한 CARD의 TYPE 입니다.
USB Port를 사용한 디바이스 연동하기
AndroidManifest.xml 파일에 아래와 같이 권한 설정을 해줍니다.
<uses-feature android:name="android.hardware.usb.host" />
근데 이놈은 NFC와 달리 Protection Level이 높아서 사용자에게 명시적으로 권한을 받아야 합니다.
NFC 처럼 USB 통신도 Activity에서 이벤트를 받도록 개발할 예정이니 해당 화면이 실행되는 onCreate()함수에 아래와 같이 구현합니다.
val usbBroadcastReceiver = UsbBroadcastReceiver()
val usbManager : UsbManager? = getSystemService(Context.USB_SERVICE) as UsbManager
val usbReader = Reader(usbManager)
var usbDevice: UsbDevice? = null
val devices : HashMap<String, UsbDevice> = usbManager.deviceList()
if(devices != null && devices.size() > 0){
var deviceKey : String? = null
for(key in devices.keySet()){
if(deviceKey == null){
usbDevice = devices.get(key)
break
}
}
if(usbDevice != null && usbManager.hasPermission(usbDevice) == false){
// 권한이 없으므로 사용자에게 권한 요청
usbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(MyNfcActivity.this, 0, Intent(ACTION_USB_PERMISSION), 0))
}else if(usbDevice != null && usbManager.hasPermission(usbDevice) == true){
// 권한이 있으므로 USB Port OPEN
...
}
Activity 에서 인식 EVENT를 받아야 하므로 NFC 처럼 onResume() 함수에 아래 코드를 추가합니다.
val usbBroadcastReceiver = UsbBroadcastReceiver()
val myIntentFilter = IntentFilter()
myIntentFilter.addAction(ACTION_USB_PERMISSION)
myIntentFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED)
registerReceiver(usbBroadcastReceiver, myIntentFilter)
Activity가 비활성화 되었을 때 EVENT를 받지 않도록 아래 코드를 추가합니다.
if(usbBroadcastReceiver != null){
unregisterReceiver(usbBroadcastReceiver);
usbBroadcastReceiver = null;
}
권한과 이벤트 처리를 완료했으면 CARD 인식 시 USB Port로 넘어오는 값을 받아 처리하는 부분 개발이 필요합니다.
연동 규격은 디바이스 회사에 요청해 받아야 합니다.
'android Tip' 카테고리의 다른 글
Coroutine - part2 (0) | 2020.12.28 |
---|---|
Coroutine - part1 (0) | 2020.12.25 |
Custom 버튼 만들기 (0) | 2020.12.21 |
숫자에 콤마 추가 시 주의할 점 (0) | 2020.12.11 |
모두가 사용하지만 모두가 모르는 좌표계 이해하고 넘어가기 (0) | 2020.11.25 |