欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android實(shí)現(xiàn)藍(lán)牙聊天功能

 更新時(shí)間:2018年06月02日 14:03:49   作者:paul_zzq  
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)藍(lán)牙聊天功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

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

本篇我將緊接著上篇結(jié)尾所寫,一起來看下手機(jī)之間如何通過藍(lán)牙實(shí)現(xiàn)文字聊天。

先貼出上篇的一些demo;

當(dāng)點(diǎn)擊圖上的兩個(gè)列表中的任何一個(gè)列表,執(zhí)行如下代碼:

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();

此藍(lán)牙聊天工具最后實(shí)現(xiàn)的效果是這樣的:

將回到聊天主界面:

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

在此,我將重點(diǎn)介紹下BluetoothChatService類中的連接流程;
因?yàn)樗{(lán)牙聊天是兩個(gè)手機(jī)之間進(jìn)行通訊,所以他們互為主機(jī)和從機(jī),主要思路以及步驟如下:

1.開一個(gè)線程獲取socket去連接藍(lán)牙;
2.開一個(gè)線程獲監(jiān)聽藍(lán)牙傳入的連接,如果連接被接受的話,再開啟第三個(gè)線程去處理所有傳入和傳出的數(shù)據(jù);

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:藍(lán)牙連接線程
 * @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(), "關(guān)閉連接失敗" + e2);
 }
 // 開啟聊天接收線程
 startChat();
 return;
 }
 synchronized (BluetoothChatService.this) {
 mConnectThread = null;
 }
 connected(mmSocket, mmDevice);
 }
 public void cancel() {
 try {
 mmSocket.close();
 } catch (IOException e) {
 LogUtils.getInstance().e(getClass(), "關(guān)閉連接失敗" + e);
 }
 }
}
/**
 * 監(jiān)聽傳入的連接
 */
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-循環(huán)執(zhí)行中-");
 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:
 // 沒有準(zhǔn)備好或已經(jīng)連接
 try {
 socket.close();
 } catch (IOException e) {
 LogUtils.getInstance().e(getClass(),"不能關(guān)閉這些連接" + e);
 }
 break;

 }
 }
 }
}
 LogUtils.getInstance().e(getClass(), "結(jié)束mAcceptThread");
}

 public void cancel() {
 LogUtils.getInstance().e(getClass(), "取消 " + this);
 try {
 mmServerSocket.close();
 } catch (IOException e) {
 LogUtils.getInstance().e(getClass(), "關(guān)閉失敗" + 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 = "";
 // 循環(huán)監(jiān)聽消息
 while (true) {
 try {
 byte[] buffer = new byte[256];
 bytes = mmInStream.read(buffer);
 String readStr = new String(buffer, 0, bytes);// 字節(jié)數(shù)組直接轉(zhuǎn)換成字符串
 String str = bytes2HexString(buffer).replaceAll("00", "").trim();
 if (bytes > 0) {// 將讀取到的消息發(fā)到主線程
  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) {
 // 在重新啟動(dòng)監(jiān)聽模式啟動(dòng)該服務(wù)
 startChat();
 }
 break;
 }
 }
}
/**
 * 寫入OutStream連接
 * 
 * @param buffer
 * 要寫的字節(jié)
 */
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);
 }
 }
 }

大概的流程就是上面三個(gè)線程里面所展現(xiàn)的,當(dāng)然具體情況,根據(jù)項(xiàng)目來,比如藍(lán)牙協(xié)議協(xié)議解析這塊的根據(jù)協(xié)議定義的方式來進(jìn)行解析;

代碼中牽扯的到的藍(lán)牙連接狀態(tài)的改變,用到的handle,直接把狀態(tài)發(fā)送至activity,通知activity更新;

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

當(dāng)點(diǎn)擊發(fā)送按鈕時(shí),將文本輸入框中的文字發(fā)送數(shù)據(jù)的方法:

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);
 }
}
//調(diào)用BluetoothChatService類中的write進(jìn)行數(shù)據(jù)發(fā)送
public void write(byte[] out) {
 ConnectedThread r;
 synchronized (this) {
 if (mState != STATE_CONNECTED)
 return;
 r = mConnectedThread;
 }
 r.write(out);
}

如此,藍(lán)牙聊天的流程就是這樣,如果退出聊天的時(shí)候,停止所有線程;

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;
 }
}

相信看完本篇文章,在安卓藍(lán)牙連接這塊應(yīng)該問題不大了(spp協(xié)議)。

源碼地址:點(diǎn)我查看源碼

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android實(shí)現(xiàn)二級(jí)列表購物車功能

    Android實(shí)現(xiàn)二級(jí)列表購物車功能

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)二級(jí)列表購物車功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • Android開發(fā)中CheckBox的簡單用法示例

    Android開發(fā)中CheckBox的簡單用法示例

    這篇文章主要介紹了Android開發(fā)中CheckBox的簡單用法,結(jié)合實(shí)例形式分析了Android中CheckBox控件的基本功能設(shè)置與頁面布局技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2016-07-07
  • Android開發(fā)實(shí)現(xiàn)長按返回鍵彈出關(guān)機(jī)框功能

    Android開發(fā)實(shí)現(xiàn)長按返回鍵彈出關(guān)機(jī)框功能

    這篇文章主要介紹了Android開發(fā)實(shí)現(xiàn)長按返回鍵彈出關(guān)機(jī)框功能,涉及Android針對(duì)長按事件的響應(yīng)與處理相關(guān)操作技巧,需要的朋友可以參考下
    2017-09-09
  • Android實(shí)現(xiàn)Unity3D下RTMP推送的示例

    Android實(shí)現(xiàn)Unity3D下RTMP推送的示例

    像Unity3D下的RTMP或RTSP播放器一樣,好多開發(fā)者苦于在Unity環(huán)境下,如何高效率低延遲的把數(shù)據(jù)采集并編碼實(shí)時(shí)推送到流媒體服務(wù)器,實(shí)現(xiàn)Unity場景下的低延遲推拉流方案。本文介紹幾種RTMP推送的方案
    2021-06-06
  • Android ListView 實(shí)例講解清晰易懂

    Android ListView 實(shí)例講解清晰易懂

    這篇文章主要通過實(shí)例介紹了Android ListView,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09
  • Android控件之GridView用法實(shí)例分析

    Android控件之GridView用法實(shí)例分析

    這篇文章主要介紹了Android控件之GridView用法,通過繪制九宮格的實(shí)例形式分析了GridView可滾動(dòng)網(wǎng)格的實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-09-09
  • Android實(shí)現(xiàn)圓形圖片或者圓角圖片

    Android實(shí)現(xiàn)圓形圖片或者圓角圖片

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)圓形圖片或者圓角圖片的代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • 關(guān)于Android Studio封裝SDK的那些事兒

    關(guān)于Android Studio封裝SDK的那些事兒

    這篇文章主要給大家介紹了關(guān)于Android Studio封裝SDK的那些事兒,文中通過圖文以及示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-09-09
  • 詳解Kotlin Android開發(fā)中的環(huán)境配置

    詳解Kotlin Android開發(fā)中的環(huán)境配置

    這篇文章主要介紹了詳解Kotlin Android開發(fā)中的環(huán)境配置的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • 詳解Android?GLide圖片加載常用幾種方法

    詳解Android?GLide圖片加載常用幾種方法

    這篇文章主要為大家介紹了詳解Android?GLide圖片加載常用幾種方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11

最新評(píng)論