액세서리 인터페이스를 내장한 임베디드 안드로이드 애플리케이션 개발
  • 2013-12-06
  • 편집부

모바일과 태블릿 기기들은 이제 우리생활에서 없어서는 안될 필수적인 기기로 정착되었으며 그 역할 또한 점차 확대되고 있다. 본고에서는 모바일 애플리케이션 개발에 필요한 다양한 개발 팁에 대하여 알아본다. 

글 | 데이비드 플라워즈(David Flowers)
수석 애플리케이션 엔지니어
마이크로칩 테크놀로지

개요
일상 생활에서 모바일과 태블릿 기기의 역할이 점점 확대되고 있다. 이로 인해, 사용자들은 개인 헬스 기구나 의료장비와 같은 다른 전자 제품들과의 인터페이스 기능을 포함한 자신의 모바일 기기로 보다 다양한 일을 처리하기를 기대한다. 이러한 모바일 기기가 제공하는 풍부한 사용자 인터페이스 가용성 및 연결성은 여러 임베디드 애플리케이션에 폭넓은 가능성이 있음을 보여준다. 그러나 이를 위해서는 우선 임베디드 개발자들이 임베디드 분야에서 벗어나 모바일 애플리케이션 개발 분야로 뛰어들어야 한다. 보다 강력한 프로세서에 기반한 애플리케이션의 개발자들에게는 모바일/태블릿용 애플리케이션 개발로의 전환이 비교적 수월할 수 있다. 반면 보다 작은 프로세서를 이용하는 애플리케이션 개발자들의 경우, 모바일 애플리케이션 개발은 기존과 다른 지식을 요하는 전혀 새로운 경험이 될 것이다. 구글은 안드로이드™ 디바이스용 개발에 도움이 될만한 여러 가지 팁을 제공하고 있다. 구글 웹사이트(http://developer.android.com/index.html)에서는 모바일 애플리케이션 개발 방법에 관한 여러 유용한 정보와 튜토리얼들을 찾아볼 수 있다. 안드로이드 애플리케이션들은 주로 자바로 작성되므로, 자바의 기초 관련 서적을 참조하는 것 또한 도움이 될 것이다. 자바 개발에 대한 내용은 인터넷에서도 많은 관련 정보를 찾아볼 수 있다.

애플리케이션 개발시 유의사항
임베디드 개발 작업에서 모바일 및 태블릿용 애플리케이션 개발로 전환할 경우, 개발자들은 다음 사항을 유의해야 한다. 모바일/태블릿은 수년 전만 해도 임베디드 플랫폼으로 분류됐으나, 현재 시장에서는 일반 컴퓨터와 동일하거나 매우 유사한 운영체제를 실행하고 있다. 이들은 다수의 애플리케이션을 실행하는 멀티 스레드와 멀티코어 머신을 기반으로, 여러 형태의 연결을 유지하는 동시에 사용자 인터페이스를 함께 제공한다. 이러한 다양한 태스크들은 애플리케이션 개발에서 스레딩을 통해 처리된다. 스레딩은 한 프로세스 내에서 프로그램 실행이 분기됨으로써, 동시에 실행될 수 있는 두 세트의 코드를 형성한다. 한 세트의 코드 진행을 위해 이벤트가 발생할 때까지 대기해야 할 경우에도 다른 스레드는 실행을 지속할 수 있다. 스레딩에 대한 이해는 모든 모바일 애플리케이션 개발에 매우 중요하다. 모바일 장치에서 웹이나 블루투스(Bluetooth짋)또는 USB 연결 등을 사용하는 태스크들은 실행 중인 스레드를 불특정한 시간 동안 혹은 무한정 긴 시간 동안 블로킹할 수 있다. 적절한 스레딩이 이루어지지 않을 경우, 해당 애플리케이션의 사용자 인터페이스가 잠금(lock-up) 상태가 되어 이들 태스크가 완료될 때까지 응답하지 않는 결과를 초래할 수 있다.
스레드의 이용은 프로그램 개발에 동시성(concurrency)의 새로운 문제를 야기한다. 두 개 이상의 스레드가 동시에 실행될 경우, 데이터가 두 스레드 사이를 지나가야 하거나 혹은 동일한 데이터를 두 스레드가 판독/수정해야 한다면 매우 복잡한 데이터 액세스 문제가 발생할 수 있다. 각 스레드의 실행시간을 알 수 없으므로, 한 스레드 내의 변수를 수정하는 것과 동시에 두 번째 스레드가 이를 읽으려 할 수 있다. 자바는 동일한 데이터를 동시에 액세스하고자 하는 두 개의 스레드와 관련하여, 동기화 문제를 해결할 수 있는 매우 유용한 키워드를 제공한다. 동기화된 키워드는 개발자들이 하나의 객체(대개는 공유된 객체)를 자동 추적하는 섹션들을 생성할 수 있도록 함으로써, 한 스레드가 동기화된 섹션 내부에 있을 경우 첫 번째 스레드가 그 섹션에서 나갈 때까지는 다른 어떠한 스레드도 들어가지 못하도록 한다.



예제 1에서 동기화된 함수들은 변수 'a'와 'b'가 함께 수정되도록 사용되며, 그 결과는 동일한 합을 얻게 된다. 동기화가 없을 경우, 'a'가 증가되었으나 'b'는 감소되기 전에 하나의 스레드가 코드의 updateVariables() 함수 ‘b’를 호출할 수 있다. 이 때 두 번째 스레드는 getSum() 루틴을 호출하므로 아주 잠깐이나마 합계가 달라지게 된다.



예제 2는 동기화된 함수 대신에 동기화된 섹션을 사용하여 동일한 효과를 달성하는 방법을 보여주고 있다. 동기화된 섹션을 이용하면 부모 객체 내의 다른 변수와 함수들을 여전히 사용할 수 있는데, 이는 락(lock)이 부모 객체 전체가 아닌 변수 'a'에만 걸리기 때문이다. 동기화 선언문들은 좀더 복잡하고 오류가 발생하기 쉽기 때문에 여러 방법들 사이에서 적절하게 선택해야 한다.
자바는 스레드 사이의 데이터나 이벤트의 안전한 전달을 위한 몇 가지 방법을 제공한다. 이러한 방법 중 하나는 핸들러(Handler)와 메시지(Message)를 이용하는 것이다. 핸들러는 우편함과 같다. 메시지를 이 우편함에 보관할 수 있으며, 관련 스레드가 한가해지는 즉시 우편함 내의 첫 번째 메시지가 스레드에 의해 처리되는 것이다. 이 방법을 이용하면 이벤트에 대한 정보나 데이터가 스레드 사이에서 안전하게 전달된다(예제 3, 4, 5).
자바 애플리케이션의 동시성에 대한 보다 상세한 내용은 다음 링크를 참조하기 바란다: http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html.



안드로이드 액티비티/애플리케이션은 라이프사이클(lifecycle)이라는 다양한 트랜지션(transition)을 거친다(그림 1). 모바일/태블릿상에서 애플리케이션에 영향을 미칠 수 있는 어떤 것이 변화할 경우, 라이프사이클 트랜지션이 발생한다. 안드로이드 OS를 겨냥한 애플리케이션을 개발할 경우 액티비티 라이프사이클을 이해하는 것이 매우 중요한데, 이는 화면 회전이나 키보드의 슬라이드 아웃, 혹은 전화를 받는 것과 같은 간단한 사용자의 상호작용들이 애플리케이션에 대해 라이프사이클 변화를 야기할 수 있기 때문이다. 또한 액티비티가 요청할 수 있는 시스템 리소스 가운데 다수는 특정 라이프사이클 상태에 구애 받지 않을 것을 명시하고 있다. 예를 들어, 브로드캐스트 리시버(Broadcast receiver)는 장치 분리 등 USB 버스 상에서 일어날 수 있는 특정한 이벤트들을 감지하는 데 사용된다. 그러나 브로드캐스트 리시버는 애플리케이션이 일시 정지할 경우 등록 해제되었다가, 애플리케이션이 재개되면 다시 등록되어야 한다.
안드로이드 OS는 이러한 이벤트들 각각의 기본 동작을 오버라이딩(overriding) 할 수 있는 방법을 제공하므로, 개발자들은 이 라이프사이클 트랜지션에 필요한 모든 기능을 추가할 수 있다. 라이프사이클 함수를 오버라이딩 하려면, 상태명을 함수로 사용하고 그 앞에 @Override 라는 키워드를 써주기만 하면 된다(예제 6).



라이프사이클 함수를 오버라이딩 할 때는 수퍼 키워드를 이용해 오버라이딩 하고 있는 부모 기능(parent func-tionallity)을 호출해야 한다. 이는 라이프사이클이 변화할 때 주로 발생하는 여러 단계들이 지속적으로 발생하도록 해준다. 그렇지 않으면, 애플리케이션이 비정상적으로 종료되거나 빌드에 실패하는 결과를 가져올 수 있다. 때로는 함수 내의 어디에서 부모 기능이 호출되는 지가 중요한 문제가 된다. 사이클의 생성 측에서 일어나는 변화(onCreate(), onStart(), onResume())의 경우 수퍼 함수는 대개 함수 시작 부분에서 호출된다. 사이클의 소멸 측에서 일어나는 변화(onPause(), onStop(), OnDestroy())에서는 대개 수퍼 호출(super call)을 함수 근처나 함수 끝에 두는 것이 중요하다.
이처럼 다양한 라이프사이클 변경을 처리 하는 문제를 피하기 위한 방법 중 하나는, 이러한 트랜지션들에서 살아남아야 하는 객체 처리 중 일부를 서비스로 보내는 것이다. 데이터 연결 객체에 대해 서비스를 이용하면, 다수의 액티비티들이 동일한 데이터 연결을 공유할 수도 있다. 서비스에 대한 보다 상세한 내용은 다음 링크를 참조하기 바란다:
http://developer.android.com/reference/android/app/Service.html.

안드로이드 OS용 액세서리를 개발할 경우, 데이터 교환을 위해 안드로이드 디바이스와 연결할 수 있는 방법들이 여러 가지 있다. 이는 OS 버전과 그 디바이스에서 사용 가능한 하드웨어 기능들에 좌우된다.  이중 주요 연결 인터페이스 세 가지가 바로 USB와 블루투스 그리고 와이파이(Wi-Fi짋)이다.
와이파이는 아마도 애플리케이션 개발에서 사용 가능한 가장 간단하고도, 문서화가 잘 되어 있는 인터페이스 중에 하나일 것이다. 타깃 액세서리가 HTTP 서버를 가지고 있을 경우에는 모바일/태블릿 상의 브라우저를 사용할 수 있으므로, 맞춤형 애플리케이션조차도 필요하지 않다. 또한 맞춤형 개발을 필요로 하지 않는 여러 telnet/ftp 타입의 애플리케이션들도 제공되고 있다. 자바에서는 오래 전부터 네트워크 API를 제공하고 있으므로, 맞춤형 애플리케이션이 필요할 경우 인터넷과 인쇄물을 통해 이에 대한 다양한 참고 자료를 얻을 수 있다. 애플리케이션이 네트워킹 API를 사용하기 위해서는 하나의 안드로이드 OS 특정 항목이 애플리케이션에 추가되어야 한다. AndroidManafest.xml 파일에 아래 상자 안의 라인을 추가해야 네트워크 API에 액세스 할 수 있다(예제 7).
액세서리 인터페이싱을 위해 안드로이드에서 와이파이를 사용할 경우, 주된 단점 중 하나는 안드로이드가 현재로선 애드혹 네트워킹을 지원하지 않는다는 것이다. 따라서 와이파이 액세서리가 동작하기 위해서는 네트워크 인프라스트럭쳐(infrastructure) 모드 지원이 필요하다. 홈 라우터에 항상 와이파이로 연결되는 온도조절 장치와 같은 일부 애플리케이션들에서는 잘 작동하지만, 대부분의 모바일 액세서리에서는 문제가 된다.
블루투스는 무선 액세서리에 있어 차선의 옵션이다. 서로 다른 안드로이드 OS 버전들은 서로 다른 블루투스 디바이스를 지원한다. 안드로이드 v2.x 버전들은 시리얼 포트 프로파일(SPP)을 지원하나, 이 OS 버전을 탑재한 일부 디바이스의 경우 이 기능을 이용할 수 없다. SPP 프로파일은 사전에 정의된 데이터 포맷이 없는 맞춤형 애플리케이션을 개발하는 데 유용하다. v3.x는 보다 특화된 액세서리용으로, 헤드셋과 A2DP(Advanced Audio Distribution Profile)를 지원한다. 안드로이드 OS 버전 4.x는 헬스 디바이스 프로파일(HDP)을 지원한다. 안드로이드 개발자를 위한 아래 웹사이트에서는 디바이스에서의 블루투스 기능 사용 예제와 함께, 사용 가능한 항목에 대한 다양한 정보를 제공하고 있다: http://developer.android.com/guide/topics/wireless/bluetooth.html.



USB는 안드로이드 장치에서의 데이터 통신을 위한 최신 기법  중 하나이다. 안드로이드 OS 2.3.4 버전 이전의 USB 포트는 디바이스 제조업체가 원하는 임의의 기능 전용으로 사용됐으며, 애플리케이션 개발자가 실제로 이 포트를 활용하는 것은 불가능했다. 안드로이드 OS v2.3.4 및 v3.1 업데이트에 이르러서야 USB 포트를 액세서리 개발에 이용할 수 있는 기능이 추가됐다.
안드로이드 버전 3.1 이후부터는 USB 호스트 API가 갖춰져, 이 기능을 갖춘 안드로이드 디바이스에 연결된 표준 USB 주변장치에 액세스할 수 있게 되었다.  이 OS는 또한 HID(Human Interface Device) 및 MSD(Mass Storage Device)와 같은 여러 디바이스 클래스에 대한 지원 기능도 내장하고 있다. 사용자들은 이 내장 드라이버를 통해, 일반 컴퓨터에서 사용하던 방식 그대로 USB 주변장치를 원활하게 활용할 수 있다. 지원 기능을 내장하지 않은 주변장치의 경우, USB 호스트 API는 애플리케이션 개발자가 낮은 수준의 간단한 API 집합을 통해 USB 엔드포인트(endpoint)에 연결해 직접 통신할 수 있도록 한다(예제 8).애플리케이션이 USB 호스트 API에 대한 승인을 얻기 위해서는 AndroidManafest.xml 파일의 라이브러리 이용을 선언해야 한다(예제 9).
또한 특정 주변장치가 USB 포트에 꽂히면 애플리케이션이 자동으로 실행되도록 하는 경우, 디바이스 필터를 설정하면 된다. AndroidManafest.xml 파일에서 USB_DEVICE_ATTACHED 이벤트와 연관된 인텐트 필터(intent filter)를 생성하고 이를 필터 파일(이 예제에서는 “xml/device_filter.xml”)에 연관시킨다(예제 10).
device_filter.xml 파일은 애플리케이션을 실행하는 디바이스에 대한 정보를 포함하고 있다. 이는 VID (Vendor ID)/ PID(Product ID) 쌍이나 Vendor ID(VID)/ Product ID (PID) 클래스, 서브클래스 및 프로토콜 집합일 수 있다(예제 11).
애플리케이션 개발자들은 태그의 일부 속성을 제외시킴으로써 좀더 포괄적으로 만들 수도 있다. 예를 들어, “프로덕트-id(product-id)” product-id속성이 없을 경우, 벤더-id(Vendor-id)가 일치하는 모든 디바이스에서 애플리케이션이 실행되도록 한다. USB 호스트 모드에 대한 보다 상세한 내용과 예제는 아래 안드로이드 개발자 웹사이트에서 찾아볼 수 있다:
http://developer.android.com/guide/topics/usb/host.html. 

기존의 많은 안드로이드 디바이스는 USB 호스트를 위한 하드웨어를 지원하지 않았으므로, 구글은 안드로이드 디바이스의 표준 USB 드라이버에 오픈 액세서리(OpenAccessory) 프레임워크를 추가했다. 오픈 액세서리 프레임워크는 맞춤형 USB 트래픽을 위해 USB 포트의 표준 USB 주변장치 기능을 액세스할 수 있는 메커니즘을 제공한다. 오픈 액세서리 프로토콜은 먼저 USB 포트에 대한 사용자 정의(custom), 벤더 클래스(vendor-class) 컨트롤 전송 명령 교환으로 이루어지며, 이는 장치 제조업체에 의해 개발된 것이다. 이 명령들은 USB 드라이버를 액세서리 모드로 전환시킨다. 이는 USB USB 주변장치가 버스에서 분리되어 구글의 벤더 ID와 두 가지 특정 제품 ID 가운데 하나를 가지고 액세서리 모드로 다시 연결되도록 한다.  이 모드에는 애플리케이션이 액세스할 수 있는 벤더 클래스 인터페이스가 있다.
오픈 액세서리 프레임워크는 파일스트림(FileStream) 스타일의 인터페이스를 애플리케이션에 알려준다. 데이터는 파일이 판독/기록되는 방법과 유사한 방식으로 스트림에 기록 및 판독된다. 이것은 USB 주변장치(USB 패킷 크기 기반의 인터페이스를 내장한)를 위한 대부분의 펌웨어 구현과는 다르다. 이로 인해 애플리케이션 개발자와 액세서리 펌웨어 개발자 간에 몇 가지 주지해야 문제들이 야기된다.
안드로이드 디바이스의 USB 드라이버는 파일스트림을 수신하므로, 특정 명령용 데이터 내에 있을 수 있는 논리적 중단점을 인지하지 못한다. 애플리케이션의 쓰기 기능에 대한 각각의 두 호출에서 얻은 데이터를 통해 패킷들을 동일한 USB 패킷으로 모을 수 있다. USB 패킷 수신 시, 펌웨어는 여기에 애플리케이션의 쓰기 기능에 대한 각각의 두 호출에서 얻은 정보가 포함될 수 있다는 것을 인식하고 있어야 한다.
애플리케이션의 쓰기 기능에 대한 단일 호출이 다수의 USB 패킷들에 걸쳐 프래그먼테이션(fragmentation) 될 수도 있다. 안드로이드 디바이스 상의 USB 드라이버는 이 데이터를 패킷으로 쪼갠 후 이를 액세서리로 전송한다. 액세서리는 이 데이터를 원하는 포맷으로 다시 합칠 수 있어야 한다.



패킹(packing)과 프래그먼테이션이 동시에 일어날 수도 있다(그림 2). 예를 들어, 오픈 액세서리 프레임워크는 현재 64 바이트 크기의 패킷들을 이용하고 있다. 애플리케이션이 쓰기 기능을 잇따라 두 번 호출하면: 첫 번째 호출은 20 바이트의 데이터를 전송한다. 두 번째 호출은 64 바이트의 데이터를 전송한다. USB 드라이버가 스트림에서 데이터를 취하여 버스를 통해 전송하는 타이밍에 따라, 두 개의 데이터 덩어리는 84 바이트 크기의 데이터 블록 하나로 패킹될 수도 있다. 이후 USB 드라이버는 이 데이터 스트림을 USB 크기의 패킷들로 쪼갠다. 그리고는 첫 64 바이트의 데이터를 전송한 뒤 나머지 20 바이트 크기의 패킷을 전송한다. 이때 첫 패킷은 첫 번째 쓰기로 얻어진 20 바이트 데이터와 두 번째 쓰기의 44 바이트를 포함한다.  20 바이트 크기의 두 번째 패킷은 두 번째 쓰기의 나머지 데이터들이다. 
사용자가 알아야 할 마지막 주요 문제는 USB 벌크 전송이 어떻게 이뤄지는가 하는 것이다.  USB 사양에 따르면, USB 벌크 전송이 완료되는 것은 다음과 같은 경우이다:

1) 예상된 데이터 량이 정확히 전송되었을 때.
2) 엔드포인트 크기보다 작은 패킷이 전송되거나 길이가 0인 패킷이 전송되었을 때.

엔드포인트 크기(현재 64 바이트)의 정확한 배수인 데이터 블록을 전송하고자 하는 경우, 전송을 완료하기 위해서는 데이터에 이어 길이 0의 패킷도 전송해야만 한다. 길이 0의 패킷들을 제때 전송하지 못할 경우, 데이터가 안드로이드 USB드라이버에 머무른 채 오픈 액세서리 파일스트림(Open Accessory FileStream)으로 전송되지 못해 결국은 애플리케이션으로 전송되지 못하는 결과를 가져올 수 있다.
USB 호스트 API와 마찬가지로, 오픈 액세서리 프레임워크를 이용하기 위해서는 AndroidManifest.xml 파일에서 승인을 받아야 한다(예제 12).
장치는 액세서리 모드로 들어가는 데 필요한 단계들을 수행하는 동안 전달된 문자열 정보를 토대로 애플리케이션을 자동실행 할 수 있다. 이는 USB 호스트 API와 매우 유사한 xml 파일들을 통해 이루어진다(예제 13, 14).



안드로이드 오픈 액세서리 버전 2 특징
현재 오픈 액세서리 프레임워크의 최대 단점 가운데 하나는, 이것이 안드로이드 OS의 선택적인 애드온 라이브러리라는 것이다. 제조업체에 따라 이 라이브러리의 포함 여부가 결정된다. 이는 OS 버전을 토대로 어떠한 장치에서든 이 기능이 지원될 것이라 가정할 수는 없다는 것을 의미한다. 또한 어떤 장치가 임의의 버전에서 이를 지원하더라도, 다음 번 OS 업데이트에서는 제조업체에 의해 그러한 지원이 사라질 수도 있다는 것을 의미한다.
안드로이드 4.1 젤리빈(Jelly Bean)의 출시로 안드로이드 오픈 액세서리(AOA) 프로토콜은 버전 2로 업데이트 되었다. AOA 버전 2에는 액세서리 개발을 돕기 위해 두 가지의 새로운 주요 특징들이 추가됐다. 첫 번째 주요 특징은 디지털 오디오 출력 지원 기능의 추가이다. 이는 안드로이드 디바이스에서 오디오 도크를 손쉽게 생성할 수 있게 해준다.  AOA 버전 1에서도 오디오 도크 디자인은 가능했지만, 그러기 위해서는 개발자가 독자적인 맞춤형 프로토콜을 작성하고 맞춤형 애플리케이션을 사용하여야만 했다. 이 경우 모든 표준 애플리케이션들은 여전히 헤드셋/스피커로부터 오디오를 끌어내게 된다. 반면 AOA 버전 2에서는 안드로이드 디바이스의 핵심 오디오가 모두 USB 포트로 라우팅되므로 오디오는 디바이스 상의 모든 애플리케이션 또는 기능들과 함께 동작할 수 있다. AOA 버전 2에서는 도킹되어 있을 경우 애플리케이션의 실행 여부에 관계 없이 오디오 인터페이스에 액세스할 수 있다. 액세서리 모드로 들어가기 전에 액세서리가 제조업체나 모델 스트링을 안드로이드 디바이스로 보내지 않는 한, 액세서리 실행 없이도 도킹이 가능하다.
AOA 버전 2에 추가된 두 번째 새로운 특징은 액세서리 모드로부터의 HID(Human Interface Device) 제어 기능이다. HID 인터페이스 제어 기능은 이전에는 USB 호스트 모드에서만 제공됐다. AOA 버전 2에서는 액세서리들이 HID 리포트를 관련 안드로이드 디바이스와 OS로 전송하여 사용자 입력을 제어할 수 있다.  이는 오디오 도크 제어뿐만 아니라, 마우스나 키보드, 조이스틱, 보조 장치와 같은 제어 장치나 안드로이드 모바일이나 태블릿 사용 시 사용자의 상호작용 인터페이스 변경에 사용 가능한 기타 입력형 장치들을 개발하는 데도 유용하다.
하드웨어 디자인을 안드로이드 액세서리로 개발하기 위해서는 수많은 제약과 장애물이 존재한다. 액세서리 인터페이스 개발에 있어 가용 리소스 및 그 한계가 무엇인지 아는 것은 개발자들에게 매우 중요하다. 하드웨어/펌웨어 제품 개발에서 관련 애플리케이션을 포함한 안드로이드 액세서리의 개발로 전환한다는 것은 매우 힘겨운 일이 될 수 있다. 마이크로칩에서는 이러한 전환을 돕기 위해 개발자에게 다양한 종류의 액세서리 개발에 유용할 다양한 참고자료들을 제공하고 있다. 무상으로 제공되는 펌웨어 및 안드로이드 애플리케이션 예제는 다음의 웹사이트에서 찾아볼 수 있다.  ES

- 오픈 액세서리: www.microchip.com/android
- 안드로이드를 USB 호스트로: www.microchip.com/usb
- 와이파이: www.microchip.com/wifi
- 블루투스: www.microchip.com/bluetooth

안드로이드 오픈 액세서리 프로토콜에 대한 보다 상세한 내용은 다음의 안드로이드 개발자 웹사이트에서 찾아볼 수 있다:
http://developer.android.com/tools/adk/index.html

안드로이드 OS 액세서리의 개발에 관한 문의는 다음 주소로 보낼 수 있다:
androidsupport@microchip.com. 

Apple iOS 액세서리의 개발에 관한 문의는 다음 주소로 보낼 수 있다:
applesupport@microchip.com.


 

<저작권자(c)스마트앤컴퍼니. 무단전재-재배포금지>



  • 100자평 쓰기
  • 로그인

세미나/교육/전시
TOP