VS2019 Xamarin.Android开发蓝牙通讯

第一步

新建项目

注意:不要选成移动应用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 - Visual Studio

 添加Xamarin

2.无法连接服务端的

请修改client端

MainActivity.cs文件内的代码

void Monitor() 函数内我限定了服务端是HUAWEI P30的设备,请修改为你自己做服务端的设备名称。

关于反馈说本文中例程不能搜索蓝牙的问题回答:

1.本例程可以搜索蓝牙,但没有写匹配相关的部分。如果需要请自行补充,该功能不在本例程范围之内。

2.本例程是通过自动匹配来完成蓝牙连接的不需要像平时使用蓝牙设备那样先搜索,在匹配,在通讯的过程,它是以下过程:

1.服务端不停的检测,只要有符合要求的UUID和设备名的设备来连接都允许连接,只要建立连接就给独立套接字,用于通讯

2.客户端启动后会自动发送建立连接的请求,至于要通讯什么内容可以根据需求自己定。

注意!注意!!!!!

关于如何在安卓上开发蓝牙,可以看这里的官方文档:https://developer.android.com/guide/topics/connectivity/bluetooth

  • 11
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
Xamarin.Forms 是一个跨平台的应用程序开发框架,可以用于开发 iOS、Android 和 Windows Phone 应用。在 Xamarin.Forms 中实现蓝牙扫描、配对、通讯,需要使用 Xamarin.Forms 的蓝牙插件,该插件可以让您在 Xamarin.Forms 中访问蓝牙功能。 以下是在 Xamarin.Forms 中实现蓝牙扫描、配对、通讯的步骤: 1. 安装蓝牙插件 使用 Xamarin.Forms 的蓝牙插件可以很容易地访问蓝牙功能。可以使用 NuGet 包管理器来安装蓝牙插件。 在 Visual Studio 中,选择项目,右键单击“管理 NuGet 包”,搜索“Xamarin.Forms.Bluetooth”,并安装。 2. 检查蓝牙权限 在使用蓝牙之前,需要检查应用程序是否具有蓝牙权限。可以使用 Xamarin.Essentials 库来检查权限。 在 Xamarin.Essentials 中,使用 Permissions 模块检查蓝牙权限。以下是代码示例: ``` var status = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>(); if (status != PermissionStatus.Granted) { status = await Permissions.RequestAsync<Permissions.LocationWhenInUse>(); if (status != PermissionStatus.Granted) { // Handle permission denied return; } } ``` 3. 扫描蓝牙设备 在 Xamarin.Forms 中,可以使用蓝牙插件的 CrossBluetoothLE.Current.Adapter 属性来扫描蓝牙设备。以下是代码示例: ``` var adapter = CrossBluetoothLE.Current.Adapter; adapter.ScanTimeout = TimeSpan.FromSeconds(10); adapter.DeviceDiscovered += (s, a) => { // Handle discovered devices }; await adapter.StartScanningForDevicesAsync(); ``` 4. 配对蓝牙设备 在 Xamarin.Forms 中,可以使用蓝牙插件的 CrossBluetoothLE.Current.Adapter 设备配对。以下是代码示例: ``` var device = // get the device to pair await device.ConnectAsync(); await device.PairAsync(); ``` 5. 连接蓝牙设备 在 Xamarin.Forms 中,可以使用蓝牙插件的 CrossBluetoothLE.Current.Adapter 设备连接。以下是代码示例: ``` var device = // get the device to connect await device.ConnectAsync(); ``` 6. 通讯 在连接了蓝牙设备后,可以使用蓝牙插件的 CrossDeviceBluetoothLE.Current.Device 属性来进行通讯。以下是代码示例: ``` var device = // get the connected device var service = await device.GetServiceAsync(serviceUuid); var characteristic = await service.GetCharacteristicAsync(characteristicUuid); await characteristic.WriteAsync(data); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狂奔De鸵鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值