android apk使用framework中usb接口范例(应用RtkGps分析)
2017-11-16 18:35
375 查看
1、首先需要在AndroidManifest中要监听usb设备插入的activity或service等中加入
android:resource="@xml/usb_device_filter" />
其中usb_device_filter是一个自己编写的文件,里面描述的是希望接管的usb设备信息。如:
</resources>
主要是vendor-id和product-id的值与usb设备一致。
2、首先在MainActivity中当mNavDrawerServerSwitch被checked时,start RtkNaviService,在onStartCommand中执行processStart,在processStart中执行UsbToRtklib.start(),在UsbToRtklib.start()执行UsbReceiver.start(),在UsbReceiver.start()中增加usb事件的检测:
f = new IntentFilter();
f.addAction(ACTION_USB_DEVICE_ATTACHED);
f.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
f.addAction(ACTION_USB_PERMISSION);
mContext.registerReceiver(mUsbStateListener, f);
mServiceThread = new UsbServiceThread();
mServiceThread.start();
执行UsbServiceThread的run时,子线程UsbServiceThread卡在serialControllerSet.block();等待serialControllerSet.open()来唤醒这个子线程。
主线程之后执行
findSupportedDevice() ---> probeDevice(),之后就new出UsbPl2303Controller,new UsbPl2303Controller 时就会拿到各种interface和endpoint的信息,可以用来传递数据用。
|
1)已连接usb设备:
主线程:
requestPermission()
|
ACTION_USB_PERMISSION
|
2)没有连接usb设备:
当连接usb设备后,就会执行:
mUsbStateListener下的
ACTION_USB_DEVICE_ATTACHED
|
onUsbDeviceAttached();
|
probeDevice() ---> probeDevice(),之后就new出UsbPl2303Controller,requestPermission()
|
ACTION_USB_PERMISSION
|
3)
主线程:
onUsbPermissionGranted()
|
mServiceThread.setController(controller); 其中执行serialControllerSet.open() ,唤醒UsbServiceThread线程。
UsbServiceThread子线程:
mUsbController.attach();
这个执行打开usb设备:
mUsbConnection = mUsbManager.openDevice(mUsbDevice);
if (mUsbConnection == null) {
throw new UsbControllerException("openDevice() failed");
}
将usb设备和本程序绑定(用本程序代替usb上层驱动来管理usb设备,如:当usb设备是U盘时,代替mass storge驱动来管理u盘,此时u盘会被卸载)
for (int i=0; i< mUsbInterfaces.length; ++i) {
if (mUsbConnection.claimInterface(mUsbInterfaces[i], true) == false) {
for (int j=0; j<i; ++j) {
mUsbConnection.releaseInterface(mUsbInterfaces[j]);
}
mUsbConnection.close();
throw new UsbControllerException("claimInterface() failed");
}
}
对usb设备的reset和初始化(就是驱动usb设备,发送controlTransfer设置usb设备)
if (!pl2303Reset()) {
detach();
throw new UsbControllerException("pl2303Reset() failed");
}
if (!pl2303Init()) {
detach();
throw new UsbControllerException("pl2303Init() failed");
}
使用之前拿到的bulk endpoint得到InputStream和OutputStream,为之后数据传输做准备。
inputStream = new UsbSerialInputStream(mUsbConnection, mBulkInEndpoint);
outputStream = new UsbSerialOutputStream(mUsbConnection, mBulkOutEndpoint);
interrupt endpoint 只能用自己封装urb(也就是UsbRequest)的方式传送usb数据给usb device;
bulk endpoint 可以使用mUsbConnection.bulkTransfer传送数据给usb device;
control endpoint可以使用mUsbConnection.controlTransfer传送数据给usb device;(control endpoint一般是endpoint 0,是不直接暴露给用户使用的,必须用这个函数操作。)
下面详解各种用法:
1、interrupt 方式数据传输:
protected static class UsbSerialInterruptListener extends Thread {
private boolean cancelRequested = false;
private UsbDeviceConnection mUsbConnection;
private ByteBuffer buffer;
private UsbRequest request;
public UsbSerialInterruptListener(UsbDeviceConnection connection, UsbEndpoint endpoint) {
this.mUsbConnection = connection;
this.setName("PL2303InterruptListener");
buffer = ByteBuffer.allocate(endpoint.getMaxPacketSize());
request = new UsbRequest();
request.initialize(connection, endpoint);
}
@Override
public void run() {
mainloop: while(!cancelRequested()) {
request.queue(buffer, buffer.capacity());
if (mUsbConnection.requestWait() == request) {
if (D) Log.v(TAG, "Interrupt received: " + buffer.toString() +
Arrays.toString(buffer.array()));
synchronized(this) {
try {
this.wait(100);
} catch (InterruptedException e) {
break mainloop;
}
if (cancelRequested) break mainloop;
}
}else {
Log.e(TAG, "requestWait failed, exiting");
break mainloop;
}
}
Log.d(TAG, "Pl2303InterruptListener thread stopped");
}
public synchronized void cancel() {
cancelRequested = true;
this.notify();
}
private synchronized boolean cancelRequested() {
return this.cancelRequested;
}
}
2、bulk的方式传输数据
bulk in:
protected class UsbSerialInputStream extends InputStream {
private static final int DEFAULT_READ_TIMEOUT_MS = 30000;
private int mTimeout = DEFAULT_READ_TIMEOUT_MS;
private UsbDeviceConnection mUsbConnection;
private UsbEndpoint mUsbEndpoint;
private byte rcvPkt[] = null;
public UsbSerialInputStream(UsbDeviceConnection connection,
UsbEndpoint bulkInEndpoint,
int writeTmoutMs
) {
mUsbConnection = connection;
mUsbEndpoint = bulkInEndpoint;
mTimeout = writeTmoutMs;
rcvPkt = new byte[mUsbEndpoint.getMaxPacketSize()];
}
public UsbSerialInputStream(UsbDeviceConnection connection,
UsbEndpoint bulkInEndpoint) {
this(connection, bulkInEndpoint, DEFAULT_READ_TIMEOUT_MS);
}
@Override
public int read() throws IOException {
synchronized(this) {
int rcvd = read(rcvPkt, 0, 1);
if (rcvd == 0) throw new IOException("timeout");
return rcvPkt[0] & 0xff;
}
}
@Override
public int read(byte[] buffer, int offset, int count) throws IOException {
int rcvd;
synchronized(this) {
if (offset == 0) {
rcvd = mUsbConnection.bulkTransfer(mUsbEndpoint, buffer,
count, mTimeout);
if (rcvd < 0) throw new IOException("bulkTransfer() error");
//if (D) Log.d(TAG, "Received " + rcvd + " bytes aligned");
return rcvd;
}else {
rcvd = mUsbConnection.bulkTransfer(mUsbEndpoint,
rcvPkt,
Math.min(count, rcvPkt.length),
mTimeout);
if (rcvd < 0) throw new IOException("bulkTransfer() error");
else if (rcvd > 0) {
System.arraycopy(rcvPkt, 0, buffer, offset, rcvd);
}
if (D) Log.d(TAG, "Received " + rcvd + " bytes");
return rcvd;
}
}
}
}
bulk out:
protected class UsbSerialOutputStream extends OutputStream {
private static final int DEFAULT_WRITE_TIMEOUT_MS = 2000;
private int mTimeout = DEFAULT_WRITE_TIMEOUT_MS;
private UsbDeviceConnection mUsbConnection;
private UsbEndpoint mUsbEndpoint;
private byte sndPkt[] = null;
public UsbSerialOutputStream(UsbDeviceConnection connection,
UsbEndpoint bulkOutEndpoint,
int writeTmoutMs
) {
mUsbConnection = connection;
mUsbEndpoint = bulkOutEndpoint;
mTimeout = writeTmoutMs;
sndPkt = new byte[mUsbEndpoint.getMaxPacketSize()];
}
public UsbSerialOutputStream(UsbDeviceConnection connection,
UsbEndpoint bulkOutEndpoint) {
this(connection, bulkOutEndpoint, DEFAULT_WRITE_TIMEOUT_MS);
}
@Override
public void write(int arg0) throws IOException {
write(new byte[] { (byte) arg0 } );
}
@Override
public void write(byte[] buffer, int offset, int count) throws IOException {
synchronized(this) {
while(count>0) {
/* XXX: timeout */
int length = count > sndPkt.length ? sndPkt.length : count;
System.arraycopy(buffer, offset, sndPkt, 0, length);
int snd = mUsbConnection.bulkTransfer(mUsbEndpoint, sndPkt, length, mTimeout);
if (snd<0) throw new IOException("bulkTransfer() failed");
count -= snd;
offset += snd;
}
}
}
}
3、control方式传输:
mUsbConnection.controlTransfer(
UsbConstants.USB_DIR_OUT | UsbConstants.USB_TYPE_VENDOR,
0x01 /* set request */,
0x0000,
0x0000,
null,
0,
PL2303_INIT_TIMEOUT_MS) >= 0;
control方式一般需要看芯片手册来确定具体设置值替代上面的参数。
<intent-filter> |
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> |
</intent-filter> |
<meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" |
其中usb_device_filter是一个自己编写的文件,里面描述的是希望接管的usb设备信息。如:
<?xml version="1.0" encoding="utf-8"?> |
<resources> |
<!-- Prolific --> |
<usb-device vendor-id="1659"product-id="8963" /><!-- 0x067b 0x2303 PL2303 Serial--> |
<usb-device vendor-id="1659"product-id="4660" /><!-- 0x067b 0x1234 DCU-11 Phone Cable--> |
<usb-device vendor-id="21362"product-id="8963" /><!-- 0x5372 0x2303 Prolific2 PL2303--> |
<!-- Generic comunnication device with Abstract Control Model subclass--> |
<usb-device class="2"subclass="0"protocol="0" /> |
主要是vendor-id和product-id的值与usb设备一致。
2、首先在MainActivity中当mNavDrawerServerSwitch被checked时,start RtkNaviService,在onStartCommand中执行processStart,在processStart中执行UsbToRtklib.start(),在UsbToRtklib.start()执行UsbReceiver.start(),在UsbReceiver.start()中增加usb事件的检测:
f = new IntentFilter();
f.addAction(ACTION_USB_DEVICE_ATTACHED);
f.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
f.addAction(ACTION_USB_PERMISSION);
mContext.registerReceiver(mUsbStateListener, f);
mServiceThread = new UsbServiceThread();
mServiceThread.start();
执行UsbServiceThread的run时,子线程UsbServiceThread卡在serialControllerSet.block();等待serialControllerSet.open()来唤醒这个子线程。
主线程之后执行
findSupportedDevice() ---> probeDevice(),之后就new出UsbPl2303Controller,new UsbPl2303Controller 时就会拿到各种interface和endpoint的信息,可以用来传递数据用。
|
1)已连接usb设备:
主线程:
requestPermission()
|
ACTION_USB_PERMISSION
|
2)没有连接usb设备:
当连接usb设备后,就会执行:
mUsbStateListener下的
ACTION_USB_DEVICE_ATTACHED
|
onUsbDeviceAttached();
|
probeDevice() ---> probeDevice(),之后就new出UsbPl2303Controller,requestPermission()
|
ACTION_USB_PERMISSION
|
3)
主线程:
onUsbPermissionGranted()
|
mServiceThread.setController(controller); 其中执行serialControllerSet.open() ,唤醒UsbServiceThread线程。
UsbServiceThread子线程:
mUsbController.attach();
这个执行打开usb设备:
mUsbConnection = mUsbManager.openDevice(mUsbDevice);
if (mUsbConnection == null) {
throw new UsbControllerException("openDevice() failed");
}
将usb设备和本程序绑定(用本程序代替usb上层驱动来管理usb设备,如:当usb设备是U盘时,代替mass storge驱动来管理u盘,此时u盘会被卸载)
for (int i=0; i< mUsbInterfaces.length; ++i) {
if (mUsbConnection.claimInterface(mUsbInterfaces[i], true) == false) {
for (int j=0; j<i; ++j) {
mUsbConnection.releaseInterface(mUsbInterfaces[j]);
}
mUsbConnection.close();
throw new UsbControllerException("claimInterface() failed");
}
}
对usb设备的reset和初始化(就是驱动usb设备,发送controlTransfer设置usb设备)
if (!pl2303Reset()) {
detach();
throw new UsbControllerException("pl2303Reset() failed");
}
if (!pl2303Init()) {
detach();
throw new UsbControllerException("pl2303Init() failed");
}
使用之前拿到的bulk endpoint得到InputStream和OutputStream,为之后数据传输做准备。
inputStream = new UsbSerialInputStream(mUsbConnection, mBulkInEndpoint);
outputStream = new UsbSerialOutputStream(mUsbConnection, mBulkOutEndpoint);
interrupt endpoint 只能用自己封装urb(也就是UsbRequest)的方式传送usb数据给usb device;
bulk endpoint 可以使用mUsbConnection.bulkTransfer传送数据给usb device;
control endpoint可以使用mUsbConnection.controlTransfer传送数据给usb device;(control endpoint一般是endpoint 0,是不直接暴露给用户使用的,必须用这个函数操作。)
下面详解各种用法:
1、interrupt 方式数据传输:
protected static class UsbSerialInterruptListener extends Thread {
private boolean cancelRequested = false;
private UsbDeviceConnection mUsbConnection;
private ByteBuffer buffer;
private UsbRequest request;
public UsbSerialInterruptListener(UsbDeviceConnection connection, UsbEndpoint endpoint) {
this.mUsbConnection = connection;
this.setName("PL2303InterruptListener");
buffer = ByteBuffer.allocate(endpoint.getMaxPacketSize());
request = new UsbRequest();
request.initialize(connection, endpoint);
}
@Override
public void run() {
mainloop: while(!cancelRequested()) {
request.queue(buffer, buffer.capacity());
if (mUsbConnection.requestWait() == request) {
if (D) Log.v(TAG, "Interrupt received: " + buffer.toString() +
Arrays.toString(buffer.array()));
synchronized(this) {
try {
this.wait(100);
} catch (InterruptedException e) {
break mainloop;
}
if (cancelRequested) break mainloop;
}
}else {
Log.e(TAG, "requestWait failed, exiting");
break mainloop;
}
}
Log.d(TAG, "Pl2303InterruptListener thread stopped");
}
public synchronized void cancel() {
cancelRequested = true;
this.notify();
}
private synchronized boolean cancelRequested() {
return this.cancelRequested;
}
}
2、bulk的方式传输数据
bulk in:
protected class UsbSerialInputStream extends InputStream {
private static final int DEFAULT_READ_TIMEOUT_MS = 30000;
private int mTimeout = DEFAULT_READ_TIMEOUT_MS;
private UsbDeviceConnection mUsbConnection;
private UsbEndpoint mUsbEndpoint;
private byte rcvPkt[] = null;
public UsbSerialInputStream(UsbDeviceConnection connection,
UsbEndpoint bulkInEndpoint,
int writeTmoutMs
) {
mUsbConnection = connection;
mUsbEndpoint = bulkInEndpoint;
mTimeout = writeTmoutMs;
rcvPkt = new byte[mUsbEndpoint.getMaxPacketSize()];
}
public UsbSerialInputStream(UsbDeviceConnection connection,
UsbEndpoint bulkInEndpoint) {
this(connection, bulkInEndpoint, DEFAULT_READ_TIMEOUT_MS);
}
@Override
public int read() throws IOException {
synchronized(this) {
int rcvd = read(rcvPkt, 0, 1);
if (rcvd == 0) throw new IOException("timeout");
return rcvPkt[0] & 0xff;
}
}
@Override
public int read(byte[] buffer, int offset, int count) throws IOException {
int rcvd;
synchronized(this) {
if (offset == 0) {
rcvd = mUsbConnection.bulkTransfer(mUsbEndpoint, buffer,
count, mTimeout);
if (rcvd < 0) throw new IOException("bulkTransfer() error");
//if (D) Log.d(TAG, "Received " + rcvd + " bytes aligned");
return rcvd;
}else {
rcvd = mUsbConnection.bulkTransfer(mUsbEndpoint,
rcvPkt,
Math.min(count, rcvPkt.length),
mTimeout);
if (rcvd < 0) throw new IOException("bulkTransfer() error");
else if (rcvd > 0) {
System.arraycopy(rcvPkt, 0, buffer, offset, rcvd);
}
if (D) Log.d(TAG, "Received " + rcvd + " bytes");
return rcvd;
}
}
}
}
bulk out:
protected class UsbSerialOutputStream extends OutputStream {
private static final int DEFAULT_WRITE_TIMEOUT_MS = 2000;
private int mTimeout = DEFAULT_WRITE_TIMEOUT_MS;
private UsbDeviceConnection mUsbConnection;
private UsbEndpoint mUsbEndpoint;
private byte sndPkt[] = null;
public UsbSerialOutputStream(UsbDeviceConnection connection,
UsbEndpoint bulkOutEndpoint,
int writeTmoutMs
) {
mUsbConnection = connection;
mUsbEndpoint = bulkOutEndpoint;
mTimeout = writeTmoutMs;
sndPkt = new byte[mUsbEndpoint.getMaxPacketSize()];
}
public UsbSerialOutputStream(UsbDeviceConnection connection,
UsbEndpoint bulkOutEndpoint) {
this(connection, bulkOutEndpoint, DEFAULT_WRITE_TIMEOUT_MS);
}
@Override
public void write(int arg0) throws IOException {
write(new byte[] { (byte) arg0 } );
}
@Override
public void write(byte[] buffer, int offset, int count) throws IOException {
synchronized(this) {
while(count>0) {
/* XXX: timeout */
int length = count > sndPkt.length ? sndPkt.length : count;
System.arraycopy(buffer, offset, sndPkt, 0, length);
int snd = mUsbConnection.bulkTransfer(mUsbEndpoint, sndPkt, length, mTimeout);
if (snd<0) throw new IOException("bulkTransfer() failed");
count -= snd;
offset += snd;
}
}
}
}
3、control方式传输:
mUsbConnection.controlTransfer(
UsbConstants.USB_DIR_OUT | UsbConstants.USB_TYPE_VENDOR,
0x01 /* set request */,
0x0000,
0x0000,
null,
0,
PL2303_INIT_TIMEOUT_MS) >= 0;
control方式一般需要看芯片手册来确定具体设置值替代上面的参数。
相关文章推荐
- Android APK应用安装原理解析之AndroidManifest使用PackageParser.parserPackage原理分析
- 你不知道的Eclipse用法:使用Heap检测和分析Android应用内存
- Android平台APK分析工具包androguard的部署使用和原理分析
- 使用工具将安卓Android apk应用转换成Bar BlackBerry 10格式
- 在Windows Mobile和Wince(Windows Embedded CE)下使用.NET Compact Framework进行GPS NMEA data数据分析的开发
- Android 网络应用重点———使用HttpGet 下载apk文件并安装
- Android 网络应用重点———使用HttpGet 下载apk文件并安装
- eclipse 使用Heap检测和分析Android应用内存
- 【Android 应用开发】 Application 使用分析
- 【Android 应用开发】分析各种Android设备屏幕分辨率与适配 - 使用大量真实安卓设备采集真实数据统计
- 【Android 应用开发】 Application 使用分析
- 使用android framework源码编译自己apk问题
- Android应用开发:LoaderManager在Activity/Fragment中的使用分析
- Android HttpClient使用Cookie应用分析
- 在Windows Mobile和Wince(Windows Embedded CE)下使用.NET Compact Framework进行GPS NMEA data数据分析的开发
- Android使用定制framework开发应用
- 【Android 应用开发】 Application 使用分析
- 使用 Android快速开发框架 Afinal 0.3 快速开发网络应用相关APK
- 使用AndroidFrameworks的隐藏类开发应用 or Android使用定制framework开发应用
- 使用网络流量分析工具更好调试Android应用(转)