VS2019 Xamarin.Android开发蓝牙通讯
第一步
新建項(xiàng)目
注意:不要選成移動(dòng)應(yīng)用xamarin.Forms要選android應(yīng)用(Xamarin)?xamarin.Forms 和?Xamarin.Android還是有區(qū)別的。小項(xiàng)目就用Xamarin.Android就好了
選擇空白模板
作為通訊App 必定需要 Server端 所以我們在這里在新建一個(gè)Client端 原本的app1項(xiàng)目作為server端
在解決方案上右鍵 添加新的項(xiàng)目
繼續(xù)選 Android 應(yīng)用
起名字叫app1Client
繼續(xù)選空白模板
OK到這里第一步建立項(xiàng)目就完成了
下一步我們將開始配置項(xiàng)目了。
第二步
配置項(xiàng)目
Android在使用藍(lán)牙時(shí)需要添加4個(gè)權(quán)限
在app1項(xiàng)目上 右鍵屬性 Android清單 內(nèi)找到 所需權(quán)限 勾選
BLUETOOTH(利用這個(gè)權(quán)限去執(zhí)行藍(lán)牙通信)
BLUETOOTH_PRIVILEGED(配對(duì)連接時(shí)需要)
BLUETOOTH_ADMIN(讓app擁有啟動(dòng)設(shè)備發(fā)現(xiàn)或操縱藍(lán)牙設(shè)置,必須聲明BLUETOOTH_ADMIN權(quán)限)
注意:真機(jī)android版本6.0及以上使用藍(lán)牙搜索需要開發(fā)權(quán)限ACCESS_COARSE_LOCATION、ACCESS_FINE_LOCATION
將App1 和 App1Client 2個(gè)項(xiàng)目都添加上述權(quán)限
第三步 編寫代碼
怎么添加界面和按鈕一類的我就不詳細(xì)寫了 這里主要寫怎么實(shí)現(xiàn)通訊的部分
1.獲得藍(lán)牙設(shè)備 這需要用到?BluetoothAdapter 這個(gè)類?
private readonly BluetoothAdapter localAdapter; localAdapter = BluetoothAdapter.DefaultAdapter;localAdapter 就是默認(rèn)藍(lán)牙適配器了
BluetoothAdapter 類 提供了 藍(lán)牙適配器的狀態(tài) 以及打開藍(lán)牙 關(guān)閉藍(lán)牙等一些方法 具體內(nèi)容請(qǐng)自己點(diǎn)進(jìn)該類查看
2獲取建立服務(wù)端的監(jiān)聽和通訊線程
我先寫下思路 我們首先需要一個(gè)線程來監(jiān)聽是否有客戶端來請(qǐng)求建立連接
如果建立連接成功就去建立一個(gè)通訊線程來讀取Client端發(fā)來的數(shù)據(jù)..是不是很簡單
下面我們來是實(shí)現(xiàn)
監(jiān)聽線程方法
//在你想要啟動(dòng)監(jiān)聽線程的地方添加這個(gè)線程 Thread t = new Thread(Monitor); t.Start();public void Monitor(){BluetoothServerSocket serverSock = localAdapter.ListenUsingRfcommWithServiceRecord("Bluetooth", Java.Util.UUID.FromString("0000-0000-0000-0000-1234567"));BluetoothSocket sock = null;while (true){try{sock = serverSock.Accept();}catch (System.Exception){}Thread t = new Thread(Connected);t.Start(sock);}核心方法 localAdapter.ListenUsingRfcommWithServiceRecord
//// 摘要:// Create a listening, secure RFCOMM Bluetooth socket with Service Record.//// 參數(shù):// name:// service name for SDP record//// uuid:// uuid for SDP record//// 返回結(jié)果:// To be added.//// 異常:// T:Java.IO.IOException:// on error, for example Bluetooth not available, or insufficient permissions, or// channel in use.//// 言論:// Portions of this page are modifications based on work created and shared by the// Android Open Source Project and used according to terms described in the Creative// Commons 2.5 Attribution License.[Register("listenUsingRfcommWithServiceRecord", "(Ljava/lang/String;Ljava/util/UUID;)Landroid/bluetooth/BluetoothServerSocket;", "")]public BluetoothServerSocket ListenUsingRfcommWithServiceRecord(string name, UUID uuid);public BluetoothServerSocket ListenUsingRfcommWithServiceRecord(string name, UUID uuid); 該方法 需要個(gè)一個(gè)連接名稱和一個(gè) UUID 并返回一個(gè)BluetoothServerSocket 對(duì)象 如果你會(huì)Socket的話接下來就很簡單了。
BluetoothServerSocket 類提供了幾個(gè)建立連接的方法
Accept()方法返回了一個(gè)BluetoothSocket對(duì)象
BluetoothSocket 類提供了藍(lán)牙適配輸入輸出流的操作
public Stream OutputStream { get; } //輸入流 讀操作使用該流 public Stream InputStream { get; } //輸出流 寫操作使用該流 public BluetoothDevice RemoteDevice { get; } //遠(yuǎn)程設(shè)備屬性接下來我們要實(shí)現(xiàn)通訊線程
Thread t = new Thread(Connected);t.Start(sock);當(dāng)建立連接成功 執(zhí)行該代碼來新建一個(gè)通訊線程?
由于通訊線程需要該連接的套接字 所以我們要把建立連接成功后的套接字作為參數(shù)傳遞到線程函數(shù)內(nèi)
通訊線程方法
public void Connected(object sock){BluetoothSocket mSock = (BluetoothSocket)sock;byte[] rebuf = new byte[1024]; while (true){int len = mSock.InputStream.Read(rebuf,0, rebuf.Length);if (len > 0){byte[] rebuf2 = new byte[len];Array.Copy(rebuf, 0, rebuf2, 0, len);string str = System.Text.Encoding.ASCII.GetString(rebuf2);Toast.MakeText(this, str, ToastLength.Short).Show();}Thread.Sleep(100);}由于線程啟動(dòng)時(shí)傳遞的參數(shù)只能是Object對(duì)象所以先將 Object對(duì)象轉(zhuǎn)換為BluetoothSocket 對(duì)象? BluetoothSocket mSock = (BluetoothSocket)sock;
然后我們在新建一個(gè)緩沖區(qū) 用來讀取數(shù)據(jù) 由于我們現(xiàn)在還不知道將要讀取的數(shù)據(jù)有多大。我們可以先建立一個(gè)和藍(lán)牙讀取緩沖區(qū)大小一樣的byte數(shù)組?byte[] rebuf = new byte[1024]; 當(dāng)然我這里只用了1KB 藍(lán)牙的讀取緩沖區(qū)默認(rèn)好像是4KB?
接下來我們就每100毫秒?yún)^(qū)讀一下是否有數(shù)據(jù) 當(dāng)然你可以用更快的速度來讀取如果你一個(gè)包的大小很小的話
//// 摘要:// 當(dāng)在派生類中重寫時(shí),從當(dāng)前流讀取字節(jié)序列,并將此流中的位置提升讀取的字節(jié)數(shù)。//// 參數(shù):// buffer:// 字節(jié)數(shù)組。 當(dāng)此方法返回時(shí),此緩沖區(qū)包含指定的字符數(shù)組,此數(shù)組中 offset 和 (offset + count - 1) 之間的值被從當(dāng)前源中讀取的字節(jié)所替換。//// offset:// buffer 中的從零開始的字節(jié)偏移量,從此處開始存儲(chǔ)從當(dāng)前流中讀取的數(shù)據(jù)。//// count:// 要從當(dāng)前流中最多讀取的字節(jié)數(shù)。//// 返回結(jié)果:// 讀入緩沖區(qū)中的總字節(jié)數(shù)。 如果很多字節(jié)當(dāng)前不可用,則總字節(jié)數(shù)可能小于請(qǐng)求的字節(jié)數(shù);如果已到達(dá)流結(jié)尾,則為零 (0)。//// 異常:// T:System.ArgumentException:// offset 和 count 的總和大于緩沖區(qū)長度。//// T:System.ArgumentNullException:// buffer 為 null。//// T:System.ArgumentOutOfRangeException:// offset 或 count 為負(fù)數(shù)。//// T:System.IO.IOException:// 出現(xiàn) I/O 錯(cuò)誤。//// T:System.NotSupportedException:// 流不支持讀取。//// T:System.ObjectDisposedException:// 在流關(guān)閉后調(diào)用方法。public abstract int Read(byte[] buffer, int offset, int count);int len = mSock.InputStream.Read(rebuf,0, rebuf.Length);Read方法返回一個(gè)int 類型的對(duì)象 表示讀到的數(shù)據(jù)長度
如果數(shù)據(jù)長度 > 0
我們就可以解析了
byte[] rebuf2 = new byte[len]; Array.Copy(rebuf, 0, rebuf2, 0, len); string str = System.Text.Encoding.ASCII.GetString(rebuf2);新建一個(gè) 讀取到長度大小的byte數(shù)組 將讀到的數(shù)據(jù)拷貝到新的數(shù)組內(nèi)進(jìn)行解析。到這一步 一個(gè)最基礎(chǔ)的服務(wù)端就完成了
To be continued .......
下集預(yù)告:明天我們將講解如何寫一個(gè)客戶端來與服務(wù)端建立連接
-------------------------------------------------------------------------------------------------
本想把客戶端的也好好寫一篇。可惜工作太忙時(shí)間有限。
我把源碼放出來。。
BLETEST.rar_Xamarin藍(lán)牙通訊-Android代碼類資源-CSDN下載
有需求的自己下載吧
----------------------------------------------------------------------------------------
對(duì)一些大家提出的問題回答
1.說缺少文件的。應(yīng)該是缺少Xamarin
感謝下載 Xamarin - Visual Studio
?添加Xamarin
2.無法連接服務(wù)端的
?
請(qǐng)修改client端
MainActivity.cs文件內(nèi)的代碼
void Monitor() 函數(shù)內(nèi)我限定了服務(wù)端是HUAWEI P30的設(shè)備,請(qǐng)修改為你自己做服務(wù)端的設(shè)備名稱。
總結(jié)
以上是生活随笔為你收集整理的VS2019 Xamarin.Android开发蓝牙通讯的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ubuntu16.04使用360随身wi
- 下一篇: leetcode刷题之x的算术平方根