12/08/2018, 15:28

Truyền tải dữ liệu giữa Android-powered và Usb device - Part 1

Android hỗ trợ nhiều thiết bị USB ngoại vi và phụ kiện Android USB thông qua 2 mode: Usb accessory và Usb Host. Trong phần này tôi sẽ nói về việc thiết lập giao tiếp giữa thiết bị Android và Usb device trong đó Android device đóng vai trò là: Usb Host. Khi thiết bị Android-powered của bạn ở chế ...

Android hỗ trợ nhiều thiết bị USB ngoại vi và phụ kiện Android USB thông qua 2 mode: Usb accessory và Usb Host. Trong phần này tôi sẽ nói về việc thiết lập giao tiếp giữa thiết bị Android và Usb device trong đó Android device đóng vai trò là: Usb Host. Khi thiết bị Android-powered của bạn ở chế độ USB Host, nó hoạt động như 1 USB Host, cấp quyền cho bus, và liệt kê các thiết bị Usb được kết nối. Chế độ USB Host được hỗ trợ trong Android 3.1 trở lên. Sau đây là các bước để thiết kế ứng dụng Android hoạt động ở chế độ Usb Host

Những yêu cầu android Manifest:

Danh sách dưới đây mô tả những gì bạn cần để thêm vào file manifrest của ứng dụng trước khi làm việc với USB host APIs: -Vì không phải tất cả các thiết bị Android-powered đảm bảo hỗ trợ USB Host APIs, bao gồm 1 <uses-feature> element để khai báo rằng ứng dụng của bạn sử dụng chức năng: android.hardware.usb.host -Thiết lập min SDK của ứng dụng từ API Level 12 hoặc cao hơn. USB host APIs không hiện diện trên các API level trước đó. -Nếu bạn muốn ứng dụng của bạn được thông báo khi có một USB device được gắn vào, hãy chỉ định cặp <intent-filter> và <meta-data> element cho android.hardware.usb.action.USB_DEVICE_ATTACHED intent trong main activity của bạn. <meta-data> element trỏ tới file resource XML bên ngoài để khai báo thông tin xác định về thiết bị mà bạn muốn phát hiện. Trong XML resource file, khai báo <usb-device> elements cho usb device bạn muốn loc. Danh sách bên dưới mô tả các thuộc tính của <usb-device>. Nhìn chung sử dụng nhà cung cấp và mã sản phẩm nếu bạn muốn lọc cho một device riêng và sử dụng class, subclass, và giao thức nếu bạn muốn lọc cho một nhóm các thiết bị USB, như là thiết bị lưu trữ hoặc máy ảnh kỹ thuật số. Bạn có thể chỉ định none hoặc all các thuộc tính. Chỉ định không có thuộc tính phù hợp với mọi thiết bị USB vì vậy chỉ thực hiện nếu ứng dụng của bạn yêu cầu: -vendor-id -product-id -class -subclass -protocol (device or interface) Lưu resource file trong thư mục res/xml/. Tên resource file (mà không có đuôi .xml) phải giống với tên mà bạn đã chỉ định trong <meta-data> element. Định dạng của XML resource file như ví dụ dưới đây: Trong trường hợp này resource file được lưu trong res/xml/device_filter.xml và chỉ định rằng bất kỳ USB device với các thuộc tính sẽ được lọc:

Làm việc với thiết bị

Khi người dùng kết nối USB device với một Android-powered device, hệ thống Android có thể xác định xem ứng dụng của bạn có quan tâm đến thiết bị được kết nối. Nếu có, bạn có thể thiết lập giao tiếp với thiết bị nếu muốn. Để làm điều này ứng dụng của bạn phải:

  1. Discover các thiết bị USB đã kết nối bằng cách sử dụng một bộ lọc (intent filter) để nhận thông báo khi người dùng kết nối Usb device hoặc liệt kê USB đã kết nối.
  2. Hỏi người dùng về quyền kết nối tới USB device nếu chưa có.
  3. Giao tiếp với Usb device bằng đọc và ghi dữ liệu trên các interface endpoints thích hợp

Discovering một thiết bị

Ứng dụng của bạn có thể khám phá những USB device bằng cách sử dụng một intent filter để nhận thông báo khi người dùng kết nối một thiết bị hoặc liệt kê thiết bị usb đã kết nối. Sử dụng intent filter rất hữu ích nếu bạn muốn ứng dụng của bạn tự động phát hiện một thiết bị mong muốn. Liệt kê những thiết bị USB rất hữu ích nếu bạn muốn lấy một danh sách tất cả các thiết bị đã kết nối hoặc nếu ứng dụng của bạn không lọc trong một intent.

Sử dụng một Intent filter

Để ứng dụng của bạn khám phá một Usb device cụ thể, bạn có thể chỉ định một Intent filter để lọc cho android.hardware.usb.action.USB_DEVICE_ATTACHED intent. Cùng với intent filter này, bạn cần chỉ ra một resource file các thuộc tính cụ thể của Usb device như là mã nhà cung cấp và mã sản phẩm. Khi người dùng kết nối một thiết bị phù hợp với bộ lọc của bạn, hệ thống thể hiện chúng với một dialog hỏi rằng: nếu họ muốn khởi động ứng dụng của bạn. Nếu người dùng chấp nhận, ứng dụng của bạn tự động có quyền truy cập thiết bị cho đến khi ngắt kết nối. Trong activity của bạn, bạn có thể lấy được UsbDevice đại diện cho thiết bị đính kèm từ intent như thế này:

Liệt kê thiết bị

Nếu ứng dụng của bạn quan tâm đến việc kiểm tra tất cả các Usb device hiện tại đã kết nối trong khi ứng dụng của bạn đang chạy, nó có thể liệt kê những thiết bị. Sử dụng phương thức getDeviceList() để lấy một hash map của tất cả các thiết bị đã kết nối. Hash map có key là tên của USB device nếu bạn muốn lấy một thiết bị trong map. Nếu mong muốn bạn có thể cũng đạt được một iterator từ hash map và xử lý từng device một:

Xin quyền giao tiếp với một thiết bị

Trước khi giao tiếp với một thiết bị USB, ứng dụng của bạn phải có quyền từ người dùng. Hỏi quyền rõ ràng là cần thiết trong một vài tình huống như là ứng dụng của bạn liệt kê USB device đã kết nối và muốn giao tiếp với một thiết bị. Bạn phải kiểm tra quyền truy cập một device trước khi cố gắng giao tiếp với nó. Nếu không bạn sẽ nhận được một runtime error nếu người dụng hạn chế quyền truy cập của thiết bị. Để có được quyền rõ ràng, đầu tiên tạo một Broadcast receiver. Receiver này lắng nge intent để lấy broadcast khi bạn gọi requestPermission(). Gọi requestPermission() hiển thị một dialog để hỏi người dùng về quyền kết nối đến thiết bị. Như ví dụ dưới đây Để đăng ký broadcast receiver thêm code này vào phương thức  onCreate() trong activity của bạn: Để hiển thị dialog để hỏi người dùng cho quyền kết nối tới thiết bị call phương thức  requestPermission(): Khi người dùng trả lời dialog, broadcast receiver của bạn nhận intent chứa  EXTRA_PERMISSION_GRANTED đó là 1 boolean đại diện cho câu trả lời. Kiểm tra kết quả này là giá trị true trước khi kết nối tới thiết bị.

Giao tiếp với một thiết bị

Giao tiếp với một Usb device có thể đồng bộ hoặc bất đồng bộ. Trong cả 2 trường hợp bạn nên tạo một Thread mới để thực hiện việc truyền tải dữ liệu như vậy bạn sẽ không block UI thread. Để thiết lập đúng giao tiếp với một thiết bị bạn cần có được UsbInterface và UsbEndpoint thích hợp của thiết bị mà bạn muốn giao tiếp và gửi yêu cầu trên điểm cấu này với một UsbDeviceConnection. Nhìn chung code của bạn nên:

Kết thúc giao tiếp với một thiết bị

Khi bạn đã hoàn thành việc giao tiếp với thiết bị USB hoặc nếu thiết bị đã bị tách ra, đóng UsbInterface và UsbDeviceConnection bằng cách gọi releaseInterface() và close(). Để lắng nge sự kiện tách ra, tạo một broadcast receiver như sau: Tạo broadcast receiver bên trong ứng dụng không phải Manifest, cho phép ứng dụng của bạn chỉ bắt sự kiện tách khỏi trong khi đang chạy.

0