一:使用版本
一:unity版本2020.3.46
二:插件版本2.3
二:环境配置
Project Settings>>Player>>Andorid>>Api Compatiblity Level>>.Net 4.x
Project Settings>>Player>>Andorid>>Internet Access>>Require
打开 Assers/Plugins/Android/AndroidManifest 改成如下一样 主要增加了定位权限,以及更改启动入口.安卓6-11要扫描到蓝牙都是需要开启定位功能.具体可以去看安卓官网解释
<?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-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<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>
</application>
</manifest>
三:使用方法
我新建了一个场景,主要看画布里面的结点.从上到下代表着
背景 | 提示文本框(连接情况...) | 其他提示文本框(接受数据...) | 滚动视图(当扫描到一个设备时会生成一个预制体并且写上信息放到滚动视图中去) | 文本输入框(接受用户输入的设备名称) | 连接按钮 | 扫描设备按钮
用来生成信息的预制体情况,就是一个文本
然后我新建一个脚本,代码如下
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Bluethood : MonoBehaviour
{
//存储蓝牙设备名字,赋予初值是为了防止与输入文本框 ""相等
private string bleName = "-*1.ym,rt";
//保存的地址
private string bleAddress;
//保存的uuid
private string serviceUUID;
//保存的特征值
private string subscribeCharacteristic;
//表示是否开始扫描
private bool isScanning;
//表示是否已经蓝牙初始化
private bool isInit;
//设备信息预制体 当扫描到一个设备时就会创建一个实例并放到滚动视图中去
public GameObject deviceInfoPrefab;
//滚动视图的容器结点
public Transform container;
//提示的文本信息框 连接提示。。。
public Text text;
//提示的其他文本信息框 接受数据提示。。。
public Text otherText;
//输入设备用的
public InputField inputField;
//开始连接按钮
public Button startConnectBtn;
//开始扫描按钮
public Button startScanningBtn;
//以设备名字做个存储,相同名字的就忽视不在扫描
private HashSet<string> devisHashSet;
void Start()
{
devisHashSet = new HashSet<string>();
Input.location.Start(); //定位
InitBluethood();
startConnectBtn.onClick.AddListener(() =>
{
if (inputField.text.Equals(null) || inputField.text.Equals(""))
{
Show("请输入设备名称!");
return;
}
if (bleName.Equals(inputField.text) || devisHashSet.Contains(inputField.text)) //找到名字一样的设备
{
BluetoothLEHardwareInterface.StopScan(); //停止扫描
ConnectBluetooth(); //开始连接
}
else
{
Show("未找到该设备,请先扫描");
}
});
startScanningBtn.onClick.AddListener(() =>
{
StartScnnning();
});
}
/// <summary>
/// 初始化蓝牙设备
/// </summary>
private void InitBluethood()
{
if (!isInit)
{
BluetoothLEHardwareInterface.Initialize(true, false, () =>
{
Show("蓝牙初始化成功");//初始化成功执行回调
isInit = true;
},
(error) =>
{
Show("蓝牙未打开或连接失败");//初始化失败的回调响应
});
}
}
/// <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 (devisHashSet.Contains(name)) return;
CreationTextPrefab(address, name);
//扫描处理,加入设备列表
AddPeripheral(name, address);
devisHashSet.Add(name);
}, (address, name, rssi, advertisingInfo) =>
{
if (devisHashSet.Contains(name)) return;
CreationTextPrefab(address, name);
AddPeripheral(name, address);
devisHashSet.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);
game.GetComponent<Text>().text = "设备名字:" + name + " " + "地址:" + address + "\n";
game.transform.SetParent(container);
game.transform.localScale = Vector3.one;
}
/// <summary>
/// 更新存储要连接设备的名字,是否扫描到
/// </summary>
/// <param name="name"></param>
/// <param name="address"></param>
public void AddPeripheral(string name, string address)
{
if (bleName.Equals(inputField.text)) return;
bleName = name;
bleAddress = address;
}
/// <summary>
/// 开始连接设备
/// </summary>
public void ConnectBluetooth()
{
Show("开始连接设备:" + inputField.text);
try
{
BluetoothLEHardwareInterface.ConnectToPeripheral(bleAddress, null, null, (address, serviceUUID, characteristicUUID) =>
{
this.serviceUUID = serviceUUID;
this.subscribeCharacteristic = characteristicUUID;
otherText.text = "serviceUUID= " + serviceUUID + "\n";
otherText.text += "characteristicUUID= " + characteristicUUID;
SubscribeCharacteristicWithDeviceAddress();
});
}
catch (Exception e)
{
otherText.text = e.ToString();
Show("连接失败");
}
}
/// <summary>
/// 连接成功的回调
/// </summary>
private void SubscribeCharacteristicWithDeviceAddress()
{
otherText.text += "\n" + "尝试接受数据";
BluetoothLEHardwareInterface.SubscribeCharacteristicWithDeviceAddress(bleAddress, serviceUUID, subscribeCharacteristic, delegate { }, OnCharacteristicNotification);
}
private void OnCharacteristicNotification(string arg1, string arg2, byte[] arg3)
{
//Show("接收到数据");
//StringBuilder hex = new StringBuilder(arg3.Length * 2);
//foreach (byte b in arg3)
//{
// hex.AppendFormat("{0:x2}", b);
// //hex.AppendFormat(b.ToString());
// //hex.AppendFormat(b.ToString()+",");
//}
otherText.text = "连接成功=" + "arg1=" + arg1 + "arg2=" + arg2 + "\n";
otherText.text = arg3.ToString();
}
}
把脚本挂在随便一个物体上,并且赋上值
四:结果演示
有几个注意事项
1.在打开app前需要先打开设备的蓝牙
2.打开app后需要赋予位置权限
3.自己手机先与要连接的硬件配对
4.打包的apk文件最好弄成竖屏
因为本人没有设备测试,所以具体能不能用看情况而定,如果成功连接并接受到数据了希望给个反馈
最后:个人能力有限.如果有误还请指出 谢谢!