第一次寫博客,挺激動的。由於這段時間在研究android設備之間的通信問題,上網找了很多資料,都沒有一個很好的例子,只是泛泛而談。要不就是隻有通過WIFi或者USB連接PC和android設備的通信,這裏就給大家講一講android設備間的通信。
demo下載連接:http://download.csdn.net/detail/xifei66/9759238
首先是一個簡單的佈局activity_chat.xml,就是後面進行通信的交互界面
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:orientation="vertical"
tools:context=".MainActivity">
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:id="@+id/content_text"/>
</ScrollView>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/screenshot"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:id="@+id/input_edittext"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="send"
android:id="@+id/send_button"
android:onClick="onButtonClick"
/>
</LinearLayout>
</LinearLayout>
public static final String DEVICE_EXTRA_KEY = "device";
private UsbManager mUsbManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
}
@Override
protected void onResume() {
super.onResume();
final HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
if (deviceList == null || deviceList.size() == 0) {
final Intent intent=new Intent(this, InfoActivity.class);
startActivity(intent);
finish();
return;
}
if (searchForUsbAccessory(deviceList)) {
return;
}
for (UsbDevice device:deviceList.values()) {
initAccessory(device);
}
finish();
}
private boolean searchForUsbAccessory(final HashMap<String, UsbDevice> deviceList) {
for (UsbDevice device:deviceList.values()) {
if (isUsbAccessory(device)) {
final Intent intent=new Intent(this,ChatActivity.class);
intent.putExtra(DEVICE_EXTRA_KEY, device);
startActivity(intent);
finish();
return true;
}
}
return false;
}
private boolean isUsbAccessory(final UsbDevice device) {
return (device.getProductId() == 0x2d00) || (device.getProductId() == 0x2d01);
}
private boolean initAccessory(final UsbDevice device) {
final UsbDeviceConnection connection = mUsbManager.openDevice(device);
if (connection == null) {
return false;
}
initStringControlTransfer(connection, 0, "quandoo"); // MANUFACTURER
initStringControlTransfer(connection, 1, "Android2AndroidAccessory"); // MODEL
initStringControlTransfer(connection, 2, "showcasing android2android USB communication"); // DESCRIPTION
initStringControlTransfer(connection, 3, "0.1"); // VERSION
initStringControlTransfer(connection, 4, "http://quandoo.de"); // URI
initStringControlTransfer(connection, 5, "42"); // SERIAL
connection.controlTransfer(0x40, 53, 0, 0, new byte[]{}, 0, Constants.USB_TIMEOUT_IN_MS);
connection.close();
return true;
}
private void initStringControlTransfer(final UsbDeviceConnection deviceConnection,
final int index,
final String string) {
deviceConnection.controlTransfer(0x40, 52, 0, index, string.getBytes(), string.length(), Constants.USB_TIMEOUT_IN_MS);
}
public class ChatActivity extends BaseChatActivity {
private final AtomicBoolean keepThreadAlive = new AtomicBoolean(true);
private final List<String> sendBuffer = new ArrayList<>();
@Override
public void sendString(final String string) {
sendBuffer.add(string);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new Thread(new CommunicationRunnable()).start();
}
private class CommunicationRunnable implements Runnable {
@Override
public void run() {
final UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
final UsbDevice device=getIntent().getParcelableExtra(ConnectActivity.DEVICE_EXTRA_KEY);
UsbEndpoint endpointIn = null;
UsbEndpoint endpointOut = null;
final UsbInterface usbInterface = device.getInterface(0);
for (int i = 0; i < device.getInterface(0).getEndpointCount(); i++) {
final UsbEndpoint endpoint = device.getInterface(0).getEndpoint(i);
if (endpoint.getDirection() == UsbConstants.USB_DIR_IN) {
endpointIn = endpoint;
}
if (endpoint.getDirection() == UsbConstants.USB_DIR_OUT) {
endpointOut = endpoint;
}
}
if (endpointIn == null) {
printLineToUI("Input Endpoint not found");
return;
}
if (endpointOut == null) {
printLineToUI("Output Endpoint not found");
return;
}
final UsbDeviceConnection connection = usbManager.openDevice(device);
if (connection == null) {
printLineToUI("Could not open device");
return;
}
final boolean claimResult = connection.claimInterface(usbInterface, true);
if (!claimResult) {
printLineToUI("Could not claim device");
} else {
final byte buff[] = new byte[Constants.BUFFER_SIZE_IN_BYTES];
printLineToUI("Claimed interface - ready to communicate");
while (keepThreadAlive.get()) {
final int bytesTransferred = connection.bulkTransfer(endpointIn, buff, buff.length, Constants.USB_TIMEOUT_IN_MS);
if (bytesTransferred > 0) {
printLineToUI("host> "+new String(buff, 0, bytesTransferred));
}
synchronized (sendBuffer) {
if (sendBuffer.size()>0) {
final byte[] sendBuff=sendBuffer.get(0).toString().getBytes();
connection.bulkTransfer(endpointOut, sendBuff, sendBuff.length, Constants.USB_TIMEOUT_IN_MS);
sendBuffer.remove(0);
}
}
}
}
connection.releaseInterface(usbInterface);
connection.close();
}
}
@Override
protected void onStop() {
super.onStop();
keepThreadAlive.set(false);
}
}
TextView contentTextView;
EditText inputMessage;
Button input;
public abstract void sendString(final String string);
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
contentTextView= (TextView) findViewById(R.id.content_text);
inputMessage= (EditText) findViewById(R.id.input_edittext);
input= (Button)findViewById(R.id.send_button);
//監聽發送消息事件
input.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
final String inputString = inputMessage.getText().toString();
if (inputString.length() == 0) {
return;
}
sendString(inputString);
printLineToUI(getString(R.string.local_prompt2) + inputString);
inputMessage.setText("");
}
});
}
public void printLineToUI(final String line) {
runOnUiThread(new Runnable() {
@Override
public void run() {
contentTextView.setText(contentTextView.getText() + "\n" + line);
}
});
}
}
public abstract class AccessoryCommunicator {
private UsbManager usbManager;
private Context context;
private Handler sendHandler;
private ParcelFileDescriptor fileDescriptor;
private FileInputStream inStream;
private FileOutputStream outStream;
private boolean running;
public AccessoryCommunicator(final Context context) {
this.context = context;
usbManager = (UsbManager) this.context.getSystemService(Context.USB_SERVICE);
final UsbAccessory[] accessoryList = usbManager.getAccessoryList();
if (accessoryList == null || accessoryList.length == 0) {
onError("no accessory found");
} else {
openAccessory(accessoryList[0]);
}
}
public void send(byte[] payload) {
if (sendHandler != null) {
Message msg = sendHandler.obtainMessage();
msg.obj = payload;
sendHandler.sendMessage(msg);
}
}
private void receive(final byte[] payload, final int length) {
onReceive(payload, length);
}
public abstract void onReceive(final byte[] payload, final int length);
public abstract void onError(String msg);
public abstract void onConnected();
public abstract void onDisconnected();
private class CommunicationThread extends Thread {
@Override
public void run() {
running = true;
while (running) {
byte[] msg = new byte[Constants.BUFFER_SIZE_IN_BYTES];
try {
//Handle incoming messages
int len = inStream.read(msg);
while (inStream != null && len > 0 && running) {
receive(msg, len);
Thread.sleep(10);
len = inStream.read(msg);
}
} catch (final Exception e) {
onError("USB Receive Failed " + e.toString() + "\n");
closeAccessory();
}
}
}
}
private void openAccessory(UsbAccessory accessory) {
fileDescriptor = usbManager.openAccessory(accessory);
if (fileDescriptor != null) {
FileDescriptor fd = fileDescriptor.getFileDescriptor();
inStream = new FileInputStream(fd);
outStream = new FileOutputStream(fd);
new CommunicationThread().start();
sendHandler = new Handler() {
public void handleMessage(Message msg) {
try {
outStream.write((byte[]) msg.obj);
} catch (final Exception e) {
onError("USB Send Failed " + e.toString() + "\n");
}
}
};
onConnected();
} else {
onError("could not connect");
}
}
public void closeAccessory() {
running = false;
try {
if (fileDescriptor != null) {
fileDescriptor.close();
}
} catch (IOException e) {
} finally {
fileDescriptor = null;
}
onDisconnected();
}
}
public static final int USB_TIMEOUT_IN_MS = 100;
public static final int BUFFER_SIZE_IN_BYTES = 256;
}
public class InfoActivity extends AppCompatActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_info);
}
}
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name="InfoActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ChatActivity"
android:screenOrientation="landscape">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="@xml/accessory_filter" />
</activity>
<activity android:name=".ConnectActivity"
android:screenOrientation="landscape">
</activity>
<activity android:name=".device.ChatActivity"
android:screenOrientation="landscape">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="@xml/accessory_filter" />
</activity>
<activity android:name=".device.ConnectActivity"
android:screenOrientation="landscape">
<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"
android:resource="@xml/device_filter" />
</activity>
</application>
這樣就搞定了。由於是第一次寫博客,如果有什麼寫的不對或者不好的地方請各位大神指正!