国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android實現藍牙聊天功能

2019-10-22 18:10:14
字體:
來源:轉載
供稿:網友

藍牙,時下最流行的智能設備傳輸數據的方式之一,通過手機app和智能設備進行連接,獲取設備上的測量數據,我們生活中隨處可見的比如藍牙智能手環,藍牙電子秤,藍牙心電測量設備等等。

本篇我將緊接著上篇結尾所寫,一起來看下手機之間如何通過藍牙實現文字聊天。

先貼出上篇的一些demo;

Android,藍牙聊天

當點擊圖上的兩個列表中的任何一個列表,執行如下代碼:

mBtAdapter.cancelDiscovery();String info = ((TextView) v).getText().toString();String address = info.substring(info.length() - 17);Intent intent = new Intent();intent.putExtra(EXTRA_DEVICE_ADDRESS, address);setResult(Activity.RESULT_OK, intent);finish();

藍牙聊天工具最后實現的效果是這樣的:

Android,藍牙聊天

將回到聊天主界面:

public void onActivityResult(int requestCode, int resultCode, Intent data) { LogUtils.getInstance().e(getClass(), "onActivityResult " + resultCode); switch (requestCode) { case REQUEST_CONNECT_DEVICE: // 當DeviceListActivity返回與設備連接的消息 if (resultCode == Activity.RESULT_OK) { // 連接設備的MAC地址 String address = data.getExtras().getString( DeviceListActivity.EXTRA_DEVICE_ADDRESS); // 得到藍牙對象 BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); // 開始連接設備 mChatService.connect(device); } break; case REQUEST_ENABLE_BT: // 判斷藍牙是否啟用 if (resultCode == Activity.RESULT_OK) { // 建立連接 setupChat(); } else { LogUtils.getInstance().e(getClass(), "藍牙未啟用"); Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show(); finish(); } }}

在此,我將重點介紹下BluetoothChatService類中的連接流程; 
因為藍牙聊天是兩個手機之間進行通訊,所以他們互為主機和從機,主要思路以及步驟如下: 

1.開一個線程獲取socket去連接藍牙; 
2.開一個線程獲監聽藍牙傳入的連接,如果連接被接受的話,再開啟第三個線程去處理所有傳入和傳出的數據;

public synchronized void connect(BluetoothDevice device) { if (mState == STATE_CONNECTING) { if (mConnectThread != null) { mConnectThread.cancel(); mConnectThread = null; } } if (mConnectedThread != null) { mConnectedThread.cancel(); mConnectedThread = null; } mConnectThread = new ConnectThread(device); mConnectThread.start(); setState(STATE_CONNECTING);}

開線程去連接

/** * @description:藍牙連接線程 * @author:zzq * @time: 2016-8-6 下午1:18:41 */private class ConnectThread extends Thread {private final BluetoothSocket mmSocket;private final BluetoothDevice mmDevice; public ConnectThread(BluetoothDevice device) { mmDevice = device; BluetoothSocket tmp = null; try { tmp = device.createRfcommSocketToServiceRecord(MY_UUID); } catch (IOException e) { LogUtils.getInstance().e(getClass(), "socket獲取失敗:" + e); } mmSocket = tmp; } public void run() { LogUtils.getInstance().e(getClass(), "開始mConnectThread"); setName("ConnectThread"); // mAdapter.cancelDiscovery(); try { mmSocket.connect(); } catch (IOException e) { // 連接失敗,更新ui connectionFailed(); try { mmSocket.close(); } catch (IOException e2) { LogUtils.getInstance().e(getClass(), "關閉連接失敗" + e2); } // 開啟聊天接收線程 startChat(); return; } synchronized (BluetoothChatService.this) { mConnectThread = null; } connected(mmSocket, mmDevice); } public void cancel() { try { mmSocket.close(); } catch (IOException e) { LogUtils.getInstance().e(getClass(), "關閉連接失敗" + e); } }}
/** * 監聽傳入的連接 */private class AcceptThread extends Thread {private final BluetoothServerSocket mmServerSocket; public AcceptThread() { BluetoothServerSocket tmp = null; try { tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID); } catch (IOException e) { LogUtils.getInstance().e(getClass(), "--獲取socket失敗:" + e); } mmServerSocket = tmp; } public void run() { setName("AcceptThread"); BluetoothSocket socket = null; while (mState != STATE_CONNECTED) { LogUtils.getInstance().e(getClass(), "----accept-循環執行中-"); try { socket = mmServerSocket.accept(); } catch (IOException e) { LogUtils.getInstance().e(getClass(), "accept() 失敗" + e); break; }// 如果連接被接受 if (socket != null) { synchronized (BluetoothChatService.this) { switch (mState) { case STATE_LISTEN: case STATE_CONNECTING: // 開始連接線程 connected(socket, socket.getRemoteDevice()); break; case STATE_NONE: case STATE_CONNECTED: // 沒有準備好或已經連接 try { socket.close(); } catch (IOException e) { LogUtils.getInstance().e(getClass(),"不能關閉這些連接" + e); } break; } } }} LogUtils.getInstance().e(getClass(), "結束mAcceptThread");} public void cancel() { LogUtils.getInstance().e(getClass(), "取消 " + this); try { mmServerSocket.close(); } catch (IOException e) { LogUtils.getInstance().e(getClass(), "關閉失敗" + e); } }}/** * 連接成功后的線程 處理所有傳入和傳出的傳輸 */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; // 得到BluetoothSocket輸入和輸出流 try { tmpIn = socket.getInputStream(); tmpOut = socket.getOutputStream(); } catch (IOException e) { LogUtils.getInstance().e(getClass(),"temp sockets not created" + e); } mmInStream = tmpIn; mmOutStream = tmpOut; } public void run() { int bytes; String str1 = ""; // 循環監聽消息 while (true) { try { byte[] buffer = new byte[256]; bytes = mmInStream.read(buffer); String readStr = new String(buffer, 0, bytes);// 字節數組直接轉換成字符串 String str = bytes2HexString(buffer).replaceAll("00", "").trim(); if (bytes > 0) {// 將讀取到的消息發到主線程  mHandler.obtainMessage(BluetoothChatActivity.MESSAGE_READ, bytes, -1,buffer).sendToTarget(); } else {  LogUtils.getInstance().e(getClass(),"disconnected"); connectionLost(); if (mState != STATE_NONE) { LogUtils.getInstance().e(getClass(), "disconnected");startChat(); } break; } } catch (IOException e) { LogUtils.getInstance().e(getClass(), "disconnected" + e); connectionLost(); if (mState != STATE_NONE) { // 在重新啟動監聽模式啟動該服務 startChat(); } break; } }}/** * 寫入OutStream連接 *  * @param buffer * 要寫的字節 */public void write(byte[] buffer) { try { mmOutStream.write(buffer); // 把消息傳給UI mHandler.obtainMessage(BluetoothChatActivity.MESSAGE_WRITE, -1,-1, buffer).sendToTarget(); } catch (IOException e) { LogUtils.getInstance().e(getClass(),"Exception during write:" + e); } }public void cancel() { try { mmSocket.close(); } catch (IOException e) { LogUtils.getInstance().e(getClass(),"close() of connect socket failed:" + e); } } }

大概的流程就是上面三個線程里面所展現的,當然具體情況,根據項目來,比如藍牙協議協議解析這塊的根據協議定義的方式來進行解析; 

代碼中牽扯的到的藍牙連接狀態的改變,用到的handle,直接把狀態發送至activity,通知activity更新;

 /** * 無法連接,通知Activity */private void connectionFailed() { setState(STATE_LISTEN); Message msg = mHandler.obtainMessage(BluetoothChatActivity.MESSAGE_TOAST); Bundle bundle = new Bundle(); bundle.putString(BluetoothChatActivity.TOAST, "無法連接設備"); msg.setData(bundle); mHandler.sendMessage(msg);}/** * 設備斷開連接,通知Activity */private void connectionLost() { Message msg = mHandler.obtainMessage(BluetoothChatActivity.MESSAGE_TOAST); Bundle bundle = new Bundle(); bundle.putString(BluetoothChatActivity.TOAST, "設備斷開連接"); msg.setData(bundle); mHandler.sendMessage(msg);}

當點擊發送按鈕時,將文本輸入框中的文字發送數據的方法:

private void sendMessage(String message) { if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) { Toast.makeText(this, R.string.not_connected,Toast.LENGTH_SHORT).show(); return;} if (message.length() > 0) { byte[] send = message.getBytes(); mChatService.write(send); }}//調用BluetoothChatService類中的write進行數據發送public void write(byte[] out) { ConnectedThread r; synchronized (this) { if (mState != STATE_CONNECTED) return; r = mConnectedThread; } r.write(out);}

如此,藍牙聊天的流程就是這樣,如果退出聊天的時候,停止所有線程;

public synchronized void stop() { LogUtils.getInstance().e(getClass(), "---stop()"); setState(STATE_NONE); if (mConnectThread != null) { mConnectThread.cancel(); mConnectThread = null;} if (mConnectedThread != null) { mConnectedThread.cancel(); mConnectedThread = null;} if (mAcceptThread != null) { mAcceptThread.cancel(); mAcceptThread = null; }}

相信看完本篇文章,在安卓藍牙連接這塊應該問題不大了(spp協議)。

源碼地址:點我查看源碼

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 绥化市| 合江县| 静海县| 万载县| 怀远县| 高尔夫| 大连市| 两当县| 清远市| 曲松县| 沧源| 平舆县| 龙胜| 凯里市| 将乐县| 吐鲁番市| 齐齐哈尔市| 淳安县| 清原| 江西省| 宜宾县| 佛山市| 昌乐县| 贵阳市| 阜阳市| 长顺县| 松阳县| 盐源县| 宜兴市| 聊城市| 焦作市| 南雄市| 武冈市| 同仁县| 工布江达县| 海兴县| 济阳县| 孟村| 明溪县| 潼南县| 灌阳县|