Unity for Android使用蓝牙低功耗Bluetooth LE
Unity2021.3.35f1
插件:Bluetooth LE for iOS and Android v2.3.unitypackage
1、将插件资源包导入unity中
2.修改插件中的AndroidManifest文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.unity3d.player" android:installLocation="preferExternal" android:versionCode="1" android:versionName="1.0">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-feature android:name="android.hardware.bluetooth_le" android:required="false" />
<application android:icon="@drawable/app_icon" android:label="@string/app_name" android:debuggable="true">
<activity android:name="com.unity3d.player.UnityPlayerProxyActivity" android:label="@string/app_name" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen">
</activity>
<activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="@string/app_name" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.unity3d.player.UnityPlayerNativeActivity" android:label="@string/app_name" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen">
<meta-data android:name="android.app.lib_name" android:value="unity" />
<meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="true" />
</activity>
<meta-data android:name="platform_high" android:value="1" />
<meta-data android:name="enable_entitlementcheck" android:value="0" />
</application>
</manifest>
3.编写UI
2个按钮:StartScanningBtn(扫描)、DisconnectBtn(断开连接)
2个Text
1个Container(带Vertical Layout Group),用于显示扫描到的终端
4.制作预制体DeviceInfo,一个Button一个Text,点击按钮可连接蓝牙终端
预制体上挂一个脚本DeviceInfo,代码始下
using UnityEngine;
using UnityEngine.UI;
public class DeviceInfo : MonoBehaviour
{
public Button btnConnect;
public Text textName;
public Text textAddress;
}
5.编写BlueToothTest.cs代码
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
public class BlueToothTest: MonoBehaviour
{
//连接的蓝牙mac地址
private string bleAddress;
//表示是否开始扫描
private bool isScanning;
//表示是否已经蓝牙初始化
private bool isInit;
//设备信息预制体 当扫描到一个设备时就会创建一个实例并放到滚动视图中去
public GameObject deviceInfoPrefab;
//滚动视图的容器结点
public Transform container;
//提示的文本信息框 连接提示。。。
public Text text;
//提示的其他文本信息框 接受数据提示。。。
public Text otherText;
//断开连接按钮
public Button disConnectBtn;
//开始扫描按钮
public Button startScanningBtn;
//以设备名字做个存储,相同名字的就忽视不在扫描
private HashSet<string> deviceHashSet = new HashSet<string>();
//设备名、设备地址字典
private Dictionary<string, string> deviceDictionary = new Dictionary<string, string>();
void Start()
{
Input.location.Start(); //定位
InitBluethood();
startScanningBtn.onClick.AddListener(() =>
{
StartScnnning();
});
disConnectBtn.onClick.AddListener(() =>
{
DisConnect();
});
}
/// <summary>
/// 初始化蓝牙设备
/// </summary>
private void InitBluethood()
{
if (!isInit)
{
BluetoothLEHardwareInterface.Initialize(true, false, () =>
{
Show("蓝牙初始化成功");//初始化成功执行回调
isInit = true;
},
(error) =>
{
Show(error.ToString());//初始化失败的回调响应
});
}
}
/// <summary>
/// 扫描设备
/// </summary>
private void StartScnnning()
{
if (!isScanning && isInit)
{
Show("扫描设备中");
Input.location.Start(); //定位
Invoke("FindDevice", 1f);
isScanning = true;
}
}
public void FindDevice()
{
BluetoothLEHardwareInterface.ScanForPeripheralsWithServices(null, (address, name) =>
{
if (deviceHashSet.Contains(name)) return;
CreationTextPrefab(address, name);
//扫描处理,加入设备列表
AddPeripheral(name, address);
deviceHashSet.Add(name);
}, (address, name, rssi, advertisingInfo) =>
{
if (deviceHashSet.Contains(name)) return;
CreationTextPrefab(address, name);
AddPeripheral(name, address);
deviceHashSet.Add(name);
});
}
public void Show(string info)
{
text.text = info;
}
/// <summary>
/// 创建提示信息预制件
/// </summary>
/// <param name="address"></param>
/// <param name="name"></param>
private void CreationTextPrefab(string address, string name)
{
GameObject game = Instantiate<GameObject>(deviceInfoPrefab);
DeviceInfo info = game.GetComponent<DeviceInfo>();
info.textName.text = name;
info.textAddress.text = address;
game.transform.localScale = Vector3.one;
game.transform.SetParent(container);
info.btnConnect.onClick.AddListener(() =>
{
if (deviceHashSet.Contains(name)) //找到名字一样的设备
{
BluetoothLEHardwareInterface.StopScan(); //停止扫描
ConnectBluetooth(deviceDictionary[name]); //开始连接
}
});
}
/// <summary>
/// 更新存储要连接设备的名字,是否扫描到
/// </summary>
/// <param name="name"></param>
/// <param name="address"></param>
public void AddPeripheral(string name, string address)
{
deviceDictionary.Add(name, address);
}
/// <summary>
/// 开始连接设备
/// </summary>
public void ConnectBluetooth(string adress)
{
Show("开始连接设备");
try
{
BluetoothLEHardwareInterface.ConnectToPeripheral(adress, null, null, (address, serviceUUID, characteristicUUID) =>
{
otherText.text += "连接成功\n";
SubscribeCharacteristicWithDeviceAddress(address, serviceUUID, characteristicUUID);
});
}
catch (Exception e)
{
Show("连接失败");
}
}
/// <summary>
/// 连接成功的回调
/// </summary>
private void SubscribeCharacteristicWithDeviceAddress(string address, string serviceUUID, string characteristicUUID)
{
if(!string.IsNullOrEmpty(serviceUUID) && !string.IsNullOrEmpty(characteristicUUID))
{
otherText.text += "正在订阅消息:"+ serviceUUID + ":" + characteristicUUID + "\n";
bleAddress = address;
BluetoothLEHardwareInterface.SubscribeCharacteristicWithDeviceAddress(address, serviceUUID, characteristicUUID, delegate { }, OnCharacteristicNotification);
}
}
/// <summary>
/// 收到数据
/// </summary>
/// <param name="arg1"></param>
/// <param name="arg2"></param>
/// <param name="arg3"></param>
private void OnCharacteristicNotification(string arg1, string arg2, byte[] arg3)
{
//Show("接收到数据");
otherText.text = "连接成功" + "\narg1=" + arg1 + "\narg2=" + arg2 + "\n";
Show(ByteArrayToString(arg3));
}
/// <summary>
/// 断开连接
/// </summary>
public void DisConnect()
{
BluetoothLEHardwareInterface.DisconnectPeripheral(bleAddress, (bleAddress) =>
{
Show(bleAddress + "已经断开");
otherText.text = "";
isScanning = false;
});
}
/// <summary>
/// 字节组转换为字符串
/// </summary>
/// <param name="ba"></param>
/// <returns></returns>
public static string ByteArrayToString(byte[] ba)
{
string hex = BitConverter.ToString(ba);
return hex.Replace("-", "");
}
}
6.挂载脚本并赋值,打包apk运行
注:本文参考了Unity插件-适用于iOS,tvOS和Android的蓝牙LE(2.3)的测试使用方法_unity蓝牙-CSDN博客