[Android藍芽]三步實現藍芽聊天APP
阿新 • • 發佈:2019-01-02
先看下結構目錄
- ChatService.java —— 藍芽連線
- DeviceList.java —— 裝置顯示
- MainActivity.java—— 主介面
1.許可權
要獲取藍芽功能,先在AndroidManifest.xml中申請許可權
<uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
2.介面
先從比較直觀的地方 彈 起吧。
主聊天介面:Listview顯示對話,EditText編輯訊息,Button傳送訊息
裝置列表:2*ListView分別顯示已配對和搜尋到的裝置。Button按鈕開始查詢。
下面講講如何實現其功能
3.程式碼
挑幾個關鍵的地方,其它細節就不一一贅述了。
3.1 DeviceList —— 藍芽搜尋裝置功能
藍芽搜尋主要是要實現一個BroadcastReceiver 廣播接收者。
首先要註冊廣播,才能使用,新增藍芽裝置ACTION_FOUND等,如下
private IntentFilter filter = new IntentFilter(); ………………………………………………… filter.addAction(BluetoothDevice.ACTION_FOUND); filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); this.registerReceiver(mReceiver,filter);
其次就是這裡廣播接收
一旦開啟廣播搜尋,並找到裝置 接收到ACTION_FOUND的資訊,則可以從BluetoothDevice.EXTRA_DEVICE中得到搜尋到的裝置資訊,顯示到螢幕上。
如果是DISCOVERY_FINISHED,即結束搜尋。 下方程式碼為看起來方便,省略了一些不必要的。
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
String action=intent.getAction();
if(BluetoothDevice.ACTION_FOUND.equals(action)){
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // 得到裝置資訊
}else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED
.equals(action)){ //結束搜尋了 }
}
}
};
3.2 ChatService —— 藍芽連線功能
通過3個執行緒來實現。
3.2.1 AcceptThread —— 被動等待連線的執行緒
使用BluetoothServerSocket accept函式,收到連線,則保持此連線傳給 ConnectedThread
// 建立監聽執行緒,準備接受新連線。使用阻塞方式,呼叫BluetoothServerSocket.accept()
private class AcceptThread extends Thread{
private final BluetoothServerSocket mmServerSocket;
public AcceptThread(){
BluetoothServerSocket tmp = null;
try{
tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME,MY_UUID);
}catch (IOException e){}
mmServerSocket = tmp;
}
public void run(){
BluetoothSocket socket= null;
while(mState != STATE_CONNECTED){
try{
socket = mmServerSocket.accept();
}catch (IOException e) {
break;
}
if(socket != null){
connected(socket,socket.getRemoteDevice());
try{
mmServerSocket.close();
}catch (IOException e){}
}
}
}
public void cancel(){
try{
mmServerSocket.close();
}catch (IOException e){}
}
}
3.2.1 ConnectThread —— 主動發起連線的執行緒
createRfcommSocketToServiceRecord 根據UUID 發起連線,連線成功則將連線傳入ConnectedThread
// 連線執行緒,專門用來對外發出連線對方藍芽的請求並進行處理
// 建構函式裡通過BluetoothDevice.createRfcommSocketToServiceRecord(),
// 從待連線的device產生BluetoothSocket,然後在run方法中connect
// 成功後呼叫 BluetoothChatService的connnected()方法,定義cancel()在關閉執行緒時能關閉socket
private class ConnectThread extends Thread{
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device){
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
mmDevice=device;
BluetoothSocket tmp = null;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try{
// MY_UUID is the app's UUID string, also used by the server code
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
}catch (IOException e){}
mmSocket = tmp;
}
public void run(){
// Cancel discovery because it will slow down the connection
mAdapter.cancelDiscovery();
try{
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
}catch (IOException e){
connectionFailed();
// Unable to connect; close the socket and get out
try{
mmSocket.close();
}catch (IOException e2){}
//ChatService.this.start();
return;
}
synchronized(ChatService.this){
mConnectedThread = null;
}
connected(mmSocket,mmDevice);
}
public void cancel(){
/* try{
mmSocket.close();
}catch (IOException e){}*/
}
}
3.2.1 ConnectedThread —— 管理連線的執行緒
管理連線好的雙方,進行資料通訊。輸入輸出流,接收資料,傳送資料
// 雙方藍芽連線後一直執行的執行緒。建構函式中設定輸入輸出流。
// Run方法中使用阻塞模式的InputStream.read()迴圈讀取輸入流
// 然後psot到UI執行緒中更新聊天資訊。也提供了write()將聊天訊息寫入輸出流傳輸至對方,
// 傳輸成功後回寫入UI執行緒。最後cancel()關閉連線的socket
private class ConnectedThread extends Thread{
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket){
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut=null;
// Get the input and output streams, using temp objects because
// member streams are final
try{
tmpIn=mmSocket.getInputStream();
tmpOut=mmSocket.getOutputStream();
}catch (IOException e){}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run(){
byte[]buffer=new byte[1024];
int bytes;
while (true){
try{
bytes = mmInStream.read(buffer);
mHandler.obtainMessage(MainActivity.MESSAGE_READ,bytes,-1,buffer).sendToTarget();
}catch (IOException e){
connectionLost();
break;
}
}
}
public void write(byte[]buffer){
try{
mmOutStream.write(buffer);
}catch (IOException e){
Log.d("MainActivity","Send Fail");
}
mHandler.obtainMessage(MainActivity.MESSAGE_WRITE,buffer).sendToTarget();
}
public void cancel(){
try{
mmSocket.close();
}catch (IOException e){}
}
}
3.3 MainActivity—— 主聊天介面
主要是將雙方資訊顯示在上方,listview的操作,就不講了。
最後,原始碼地址奉上:https://github.com/Zweo/Bluetooth