第一步
新建项目
注意:不要选成移动应用xamarin.Forms要选android应用(Xamarin) xamarin.Forms 和 Xamarin.Android还是有区别的。小项目就用Xamarin.Android就好了
选择空白模板
作为通讯App 必定需要 Server端 所以我们在这里在新建一个Client端 原本的app1项目作为server端
在解决方案上右键 添加新的项目
继续选 Android 应用
起名字叫app1Client
继续选空白模板
OK到这里第一步建立项目就完成了
下一步我们将开始配置项目了。
第二步
配置项目
Android在使用蓝牙时需要添加4个权限
在app1项目上 右键属性 Android清单 内找到 所需权限 勾选
BLUETOOTH(利用这个权限去执行蓝牙通信)
BLUETOOTH_PRIVILEGED(配对连接时需要)
BLUETOOTH_ADMIN(让app拥有启动设备发现或操纵蓝牙设置,必须声明BLUETOOTH_ADMIN权限)
注意:真机android版本6.0及以上使用蓝牙搜索需要开发权限ACCESS_COARSE_LOCATION、ACCESS_FINE_LOCATION
将App1 和 App1Client 2个项目都添加上述权限
第三步 编写代码
怎么添加界面和按钮一类的我就不详细写了 这里主要写怎么实现通讯的部分
1.获得蓝牙设备 这需要用到 BluetoothAdapter 这个类
private readonly BluetoothAdapter localAdapter;
localAdapter = BluetoothAdapter.DefaultAdapter;
localAdapter 就是默认蓝牙适配器了
BluetoothAdapter 类 提供了 蓝牙适配器的状态 以及打开蓝牙 关闭蓝牙等一些方法 具体内容请自己点进该类查看
2获取建立服务端的监听和通讯线程
我先写下思路 我们首先需要一个线程来监听是否有客户端来请求建立连接
如果建立连接成功就去建立一个通讯线程来读取Client端发来的数据..是不是很简单
下面我们来是实现
监听线程方法
//在你想要启动监听线程的地方添加这个线程
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.
//
// 参数:
// name:
// service name for SDP record
//
// uuid:
// uuid for SDP record
//
// 返回结果:
// 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); 该方法 需要个一个连接名称和一个 UUID 并返回一个BluetoothServerSocket 对象 如果你会Socket的话接下来就很简单了。
BluetoothServerSocket 类提供了几个建立连接的方法
Accept()方法返回了一个BluetoothSocket对象
BluetoothSocket 类提供了蓝牙适配输入输出流的操作
public Stream OutputStream { get; } //输入流 读操作使用该流
public Stream InputStream { get; } //输出流 写操作使用该流
public BluetoothDevice RemoteDevice { get; } //远程设备属性
接下来我们要实现通讯线程
Thread t = new Thread(Connected);
t.Start(sock);
当建立连接成功 执行该代码来新建一个通讯线程
由于通讯线程需要该连接的套接字 所以我们要把建立连接成功后的套接字作为参数传递到线程函数内
通讯线程方法
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);
}
由于线程启动时传递的参数只能是Object对象所以先将 Object对象转换为BluetoothSocket 对象 BluetoothSocket mSock = (BluetoothSocket)sock;
然后我们在新建一个缓冲区 用来读取数据 由于我们现在还不知道将要读取的数据有多大。我们可以先建立一个和蓝牙读取缓冲区大小一样的byte数组 byte[] rebuf = new byte[1024]; 当然我这里只用了1KB 蓝牙的读取缓冲区默认好像是4KB
接下来我们就每100毫秒区读一下是否有数据 当然你可以用更快的速度来读取如果你一个包的大小很小的话
//
// 摘要:
// 当在派生类中重写时,从当前流读取字节序列,并将此流中的位置提升读取的字节数。
//
// 参数:
// buffer:
// 字节数组。 当此方法返回时,此缓冲区包含指定的字符数组,此数组中 offset 和 (offset + count - 1) 之间的值被从当前源中读取的字节所替换。
//
// offset:
// buffer 中的从零开始的字节偏移量,从此处开始存储从当前流中读取的数据。
//
// count:
// 要从当前流中最多读取的字节数。
//
// 返回结果:
// 读入缓冲区中的总字节数。 如果很多字节当前不可用,则总字节数可能小于请求的字节数;如果已到达流结尾,则为零 (0)。
//
// 异常:
// T:System.ArgumentException:
// offset 和 count 的总和大于缓冲区长度。
//
// T:System.ArgumentNullException:
// buffer 为 null。
//
// T:System.ArgumentOutOfRangeException:
// offset 或 count 为负数。
//
// T:System.IO.IOException:
// 出现 I/O 错误。
//
// T:System.NotSupportedException:
// 流不支持读取。
//
// T:System.ObjectDisposedException:
// 在流关闭后调用方法。
public abstract int Read(byte[] buffer, int offset, int count);
int len = mSock.InputStream.Read(rebuf,0, rebuf.Length);
Read方法返回一个int 类型的对象 表示读到的数据长度
如果数据长度 > 0
我们就可以解析了
byte[] rebuf2 = new byte[len];
Array.Copy(rebuf, 0, rebuf2, 0, len);
string str = System.Text.Encoding.ASCII.GetString(rebuf2);
新建一个 读取到长度大小的byte数组 将读到的数据拷贝到新的数组内进行解析。到这一步 一个最基础的服务端就完成了
To be continued .......
下集预告:明天我们将讲解如何写一个客户端来与服务端建立连接
-------------------------------------------------------------------------------------------------
本想把客户端的也好好写一篇。可惜工作太忙时间有限。
我把源码放出来。。
BLETEST.rar_Xamarin蓝牙通讯-Android代码类资源-CSDN下载
有需求的自己下载吧
----------------------------------------------------------------------------------------
对一些大家提出的问题回答
1.说缺少文件的。应该是缺少Xamarin
添加Xamarin
2.无法连接服务端的
请修改client端
MainActivity.cs文件内的代码
void Monitor() 函数内我限定了服务端是HUAWEI P30的设备,请修改为你自己做服务端的设备名称。
关于反馈说本文中例程不能搜索蓝牙的问题回答:
1.本例程可以搜索蓝牙,但没有写匹配相关的部分。如果需要请自行补充,该功能不在本例程范围之内。
2.本例程是通过自动匹配来完成蓝牙连接的不需要像平时使用蓝牙设备那样先搜索,在匹配,在通讯的过程,它是以下过程:
1.服务端不停的检测,只要有符合要求的UUID和设备名的设备来连接都允许连接,只要建立连接就给独立套接字,用于通讯
2.客户端启动后会自动发送建立连接的请求,至于要通讯什么内容可以根据需求自己定。
注意!注意!!!!!
关于如何在安卓上开发蓝牙,可以看这里的官方文档:https://developer.android.com/guide/topics/connectivity/bluetooth