行业知识
Unity安卓蓝牙
2026-11-15 12:29:48
来源:互联网转载
���接贴代码
()安卓部分
package com.example.unitybluetooth;import java.util.Dictionary;public interface BluetoothStateInterface { void onBluetoothStateON(); void onBluetoothStateOFF(); void onBluetoothScanStart(); void onBluetoothFound(String address,String name); void onBluetoothScanEnd(); void onBluetoothBondSucccess(); void onBluetoothBonded(String address,String name); void onBluetoothBonding(); void onBluetoothBondFail(); void Log(String msg);} package com.example.unitybluetooth;import android.Manifest;import android.app.Activity;import android.bluetooth.BluetoothAdapter;import android.bluetooth.BluetoothDevice;import android.bluetooth.BluetoothHeadset;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.content.pm.PackageManager;import android.util.Log;import androidx.core.app.ActivityCompat;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.Dictionary;import java.util.HashMap;import java.util.Hashtable;import java.util.Map;import java.util.Set;public class BluetoothUtil { private static final String TAG = "Main_BluetoothStateUtil"; private BluetoothAdapter bluetoothAdapter; private BluetoothStateBroadcastReceive mReceive; private Context mContext; private BluetoothStateInterface mBluetoothStateInterface; /** * 初始化 */ public void Init(BluetoothStateInterface bluetoothStateInterface) { // 获得蓝牙适配器对象 bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); mContext = getActivity(); mBluetoothStateInterface = bluetoothStateInterface; } /** * 获取蓝牙状态 * @return */ public boolean getBlueToothState() { // 获取蓝牙状态 return bluetoothAdapter.isEnabled(); } /** * 开启蓝牙 * @return */ public boolean openBlueTooth() { if (getBlueToothState()) return true; // 打开蓝牙 return bluetoothAdapter.enable(); } /** * 关闭蓝牙 * @return */ public boolean colseBlueTooth() { if (!getBlueToothState()) return true; // 关闭蓝牙 return bluetoothAdapter.disable(); } // 调用系统的请求打开蓝牙 public void gotoSystem(Context context) { Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); context.startActivity(intent); } //开始扫描 public void scanBluetooth(){ bluetoothAdapter.startDiscovery(); } //停止扫描 public void stopScanBluetooth(){ bluetoothAdapter.cancelDiscovery(); } public void bondedBluetooth(){ Set devices = bluetoothAdapter.getBondedDevices(); for (BluetoothDevice device : devices){ mBluetoothStateInterface.onBluetoothBonded(device.getAddress(),device.getName()); } } //开始配对 public void bondBluetooth(String address) { BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address); if (device.getBondState() == BluetoothDevice.BOND_NONE) { device.createBond(); } } //取消配对 public void unBondBluetooth(String address){ BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address); unPairDevice(device); } private void unPairDevice(BluetoothDevice device){ try { Method method = device.getClass().getMethod("removeBond",(Class[])null); method.invoke(device,(Object[]) null); }catch (Exception e){ mBluetoothStateInterface.Log("取消配对异常:"+e.getMessage()); } } public void connectBluetooth(String address) { } /** * 注册监听蓝牙变化 */ public void registerBluetoothReceiver() { if (mReceive == null) { mReceive = new BluetoothStateBroadcastReceive(); } IntentFilter intentFilter = new IntentFilter(); //设备被发现 intentFilter.addAction(BluetoothDevice.ACTION_FOUND); //搜索开始 intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); //搜索结束 intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); //监视蓝牙关闭和打开的状态 intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); //监视蓝牙设备与APP连接的状态 intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED); intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); //蓝牙配对 intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); intentFilter.addAction("android.bluetooth.BluetoothAdapter.STATE_OFF"); intentFilter.addAction("android.bluetooth.BluetoothAdapter.STATE_ON"); mContext.registerReceiver(mReceive, intentFilter); } /** * 取消监听蓝牙变化 */ public void unregisterBluetoothReceiver() { if (mReceive != null) { mContext.unregisterReceiver(mReceive); mReceive = null; } } /** * 蓝牙状态变化监听 */ class BluetoothStateBroadcastReceive extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { try { String action = intent.getAction(); BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); switch (action) { case BluetoothDevice.ACTION_FOUND: mBluetoothStateInterface.onBluetoothFound(device.getAddress(),device.getName()); break; case BluetoothAdapter.ACTION_DISCOVERY_STARTED: //开始搜索 mBluetoothStateInterface.onBluetoothScanStart(); break; case BluetoothAdapter.ACTION_DISCOVERY_FINISHED: //搜索完成 mBluetoothStateInterface.onBluetoothScanEnd(); break; case BluetoothDevice.ACTION_ACL_CONNECTED: //Toast.makeText(context , "蓝牙设备:" + device.getName() + "已连接", Toast.LENGTH_SHORT).show(); //Log.i(TAG, "onReceive: " + "蓝牙设备:" + device.getName() + "已连接"); break; case BluetoothDevice.ACTION_ACL_DISCONNECTED: //Log.i(TAG, "onReceive: "+"蓝牙设备:" + device.getName() + "已断开"); break; case BluetoothAdapter.ACTION_STATE_CHANGED: int blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0); switch (blueState){ case BluetoothAdapter.STATE_OFF: mBluetoothStateInterface.onBluetoothStateOFF(); break; case BluetoothAdapter.STATE_ON: mBluetoothStateInterface.onBluetoothStateON(); break; } break; case BluetoothDevice.ACTION_BOND_STATE_CHANGED: BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); switch (bluetoothDevice.getBondState()) { case BluetoothDevice.BOND_BONDED: //配对完成 mBluetoothStateInterface.onBluetoothBondSucccess(); break; case BluetoothDevice.BOND_BONDING: //正在配对 mBluetoothStateInterface.onBluetoothBonding(); break; case BluetoothDevice.BOND_NONE: //取消配对 mBluetoothStateInterface.onBluetoothBondFail(); break; } break; } }catch (Exception e){ Log.i(TAG,e.getMessage()); } } } // 设置一个 Activity 参数 private Activity _unityActivity; // 通过反射获取 Unity 的 Activity 的上下文 Activity getActivity(){ if(null == _unityActivity){ try{ Class classtype = Class.forName("com.unity3d.player.UnityPlayer"); Activity activity = (Activity) classtype.getDeclaredField("currentActivity").get(classtype); _unityActivity = activity; }catch (ClassNotFoundException e){ e.printStackTrace(); }catch (IllegalAccessException e){ e.printStackTrace(); }catch (NoSuchFieldException e){ e.printStackTrace(); } } return _unityActivity; }} 然后AndroidStudio打成aar的包放Unity的Plugins的文件夹下面
()这里贴Unity的代码
using System;using UnityEngine;namespace AndroidWrapper{ /// /// 蓝牙状态监听接口 /// public class BluetoothStateInterface : AndroidJavaProxy { /// /// 蓝牙变化委托事件 /// Action _mBluetoothStateON; Action _mBluetoothStateOFF; Action _mBluetoothScanStart; Action _mBluetoothFound; Action _mBluetoothScanEnd; Action _mBluetoothBondSucccess; Action _mBluetoothBonded; Action _mBluetoothBonding; Action _mBluetoothBondFail; Action _mLog; public BluetoothStateInterface(Action mBluetoothStateON, Action mBluetoothStateOFF, Action mBluetoothScanStart, Action mBluetoothFound, Action mBluetoothScanEnd, Action mBluetoothBondSucccess,Action mBluetoothBonded, Action mBluetoothBonding,Action mBluetoothBondFail, Action mLog) : base("com.example.unitybluetooth.BluetoothStateInterface") { _mBluetoothStateON = mBluetoothStateON; _mBluetoothStateOFF = mBluetoothStateOFF; _mBluetoothScanStart = mBluetoothScanStart; _mBluetoothFound = mBluetoothFound; _mBluetoothScanEnd = mBluetoothScanEnd; _mBluetoothBondSucccess = mBluetoothBondSucccess; _mBluetoothBonded = mBluetoothBonded; _mBluetoothBonding = mBluetoothBonding; _mBluetoothBondFail = mBluetoothBondFail; _mLog = mLog; } /// /// 蓝牙打开事件监听 /// public void onBluetoothStateON() { _mBluetoothStateON?.Invoke(); Debug.Log(GetType() + "/onBluetoothStateON()/ 蓝牙开启事件"); } /// /// 蓝牙关闭事件监听 /// public void onBluetoothStateOFF() { _mBluetoothStateOFF?.Invoke(); Debug.Log(GetType() + "/onBluetoothStateOFF()/ 蓝牙关闭事件"); } public void onBluetoothScanStart() { _mBluetoothScanStart?.Invoke(); Debug.Log($"onBluetoothScanStart"); } public void onBluetoothFound(string address, string name) { _mBluetoothFound?.Invoke(address, name); } public void onBluetoothScanEnd() { _mBluetoothScanEnd?.Invoke(); Debug.Log($"onBluetoothScanEnd"); } public void onBluetoothBondSucccess() { _mBluetoothBondSucccess?.Invoke(); Debug.Log("配对成功"); } public void onBluetoothBonded(string address,string name) { _mBluetoothBonded?.Invoke(address, name); Debug.Log($"已配对设备 {address} {name}"); } public void onBluetoothBonding() { _mBluetoothBonding?.Invoke(); Debug.Log("正在配对..."); } public void onBluetoothBondFail() { _mBluetoothBondFail?.Invoke(); Debug.Log("配对失败"); } public void Log(string msg) { _mLog?.Invoke(msg); Debug.Log($"Log {msg}"); } public override AndroidJavaObject Invoke(string methodName, object[] args) { if (methodName == "onBluetoothFound") { onBluetoothFound(args[0] as string, args[1] as string); return null; } return base.Invoke(methodName, args); } }} using UnityEngine;public abstract class MonoSingleton : MonoBehaviour where T : MonoBehaviour{ private static T instance = null; private static readonly object locker = new object(); private static bool bAppQuitting; public static T Instance { get { if (bAppQuitting) { instance = null; return instance; } lock (locker) { if (instance == null) { instance = FindObjectOfType(); if (FindObjectsOfType().Length > 1) { Debug.LogError("不应该存在多个单例!"); return instance; } if (instance == null) { var singleton = new GameObject(); instance = singleton.AddComponent(); singleton.name = "(singleton)" + typeof(T); singleton.hideFlags = HideFlags.None; DontDestroyOnLoad(singleton); } else DontDestroyOnLoad(instance.gameObject); } instance.hideFlags = HideFlags.None; return instance; } } } protected virtual void Awake() { bAppQuitting = false; } protected virtual void OnDestroy() { bAppQuitting = true; }} using System;using System.Collections;using System.Collections.Generic;using UnityEngine;namespace AndroidWrapper{ /// /// 蓝牙状态封装 /// 使用说明 /// 1、首先初始化,绑定监听事件 /// 2、可获取蓝牙状态,设置蓝牙状态 /// 3、获得监听结果 /// public class BluetoothStateWrapper : MonoSingleton { /// /// 初始化 /// /// public void Init(Action OnBluetoothStateONListener, Action OnBluetoothStateOFFListener, Action mBluetoothScanStartListener, Action mBluetoothFoundListener, Action mBluetoothScanEndListener, Action mBluetoothBondSuccess,Action mBluetoothBonded,Action mBluetoothBonding,Action mBluetoothBondFail, Action mLog) {#if UNITY_EDITOR#else MAndroidJavaObject.Call("Init",new BluetoothStateInterface(OnBluetoothStateONListener, OnBluetoothStateOFFListener, mBluetoothScanStartListener,mBluetoothFoundListener,mBluetoothScanEndListener, mBluetoothBondSuccess, mBluetoothBonded, mBluetoothBonding,mBluetoothBondFail, mLog)); registerBluetoothReceiver();#endif } /// /// 获得蓝牙状态 /// /// public bool getBlueToothState() { return MAndroidJavaObject.Call("getBlueToothState"); } /// /// 开启蓝牙 /// /// public bool openBlueTooth() { return MAndroidJavaObject.Call("openBlueTooth"); } /// /// 关闭蓝牙 /// /// public bool colseBlueTooth() { return MAndroidJavaObject.Call("colseBlueTooth"); } /// /// 搜索蓝牙 /// public void ScanBluetooth() { MAndroidJavaObject.Call("scanBluetooth"); } /// /// 停止搜索蓝牙 /// public void StopScanBluetooth() { MAndroidJavaObject.Call("stopScanBluetooth"); } public void GetBondedBluetooth() { MAndroidJavaObject.Call("bondedBluetooth"); } /// /// 蓝牙配对 /// public void BondBluetooth(string address) { MAndroidJavaObject.Call("bondBluetooth", address); } /// /// 取消配对 /// /// public void UnBondBluetooth(string address) { MAndroidJavaObject.Call("unBondBluetooth", address); } public void ConnectBluetooth(string address) { } public void DisconnectBluetooth() { } #region 私有方法 /// /// 注册蓝牙状态监听 /// void registerBluetoothReceiver() { MAndroidJavaObject.Call("registerBluetoothReceiver"); } /// /// 取消注册蓝牙状态监听 /// void unregisterBluetoothReceiver() { MAndroidJavaObject.Call("unregisterBluetoothReceiver"); } protected override void OnDestroy() { unregisterBluetoothReceiver(); base.OnDestroy(); } #endregion #region 私有变量 AndroidJavaObject _mAndroidJavaObject; public AndroidJavaObject MAndroidJavaObject { get { if (_mAndroidJavaObject == null) { _mAndroidJavaObject = new AndroidJavaObject("com.example.unitybluetooth.BluetoothUtil"); } return _mAndroidJavaObject; } } #endregion }} using System;using System.Collections;using System.Collections.Generic;using System.Threading;using UnityEngine;public class Loom : MonoBehaviour{ public static int maxThreads = 8; private static int numThreads; private static bool initialized; private List actions = new List(); List currentActions = new List(); private List delayed = new List(); private List currentDelayed = new List(); private static float curtime = 0f; private static Loom mCurrent; public static Loom current { get { Initialize(); return mCurrent; } } void Update() { curtime = Time.realtimeSinceStartup; lock (actions) { currentActions.Clear(); currentActions.AddRange(actions); actions.Clear(); } foreach (var currentAction in currentActions) { currentAction(); } lock (delayed) { currentDelayed.Clear(); foreach (var delayItem in delayed) { if (delayItem.time = maxThreads) { Thread.Sleep(1); } Interlocked.Increment(ref numThreads); ThreadPool.QueueUserWorkItem(RunAction, action); return null; } [System.Serializable] public struct DelayedQueueItem { public float time; public Action action; }} 调用方法:
using AndroidWrapper;using System;using System.Collections;using System.Collections.Generic;using System.Net;using System.Text;using UnityEngine;using UnityEngine.Android;using UnityEngine.UI;using static System.Net.Mime.MediaTypeNames;using Text = UnityEngine.UI.Text;public class UIBluetooth : MonoBehaviour{ public Text connectedInfo; public Toggle openBluetoothTog; public Button scanBtn; public Text scanText; public Button bondBtn; public Text bondText; public Button connectBtn; public Text connectText; public ScrollRect scrollRect; public Transform contentParentParent; public Transform contentParent; public bool isInit = false; public bool isBonding = false; public bool isConnecting = false; public bool isScaning = false; /// /// 设备列表 /// private List deviceList = new List(); private string currentSelectedAddress; private Action selectBluetoothAction; private void Start() { scanBtn.onClick.RemoveAllListeners(); scanBtn.onClick.AddListener(OnScan); bondBtn.onClick.RemoveAllListeners(); bondBtn.onClick.AddListener(OnBond); connectBtn.onClick.RemoveAllListeners(); connectBtn.onClick.AddListener(OnConnect); selectBluetoothAction = SelectBluetooth; RequestPermissions(); Initialize(); } private void Initialize() { isInit = true; BluetoothStateWrapper.Instance.Init(SetOnToggle, SetOffToggle, BluetoothScanStartListener, BluetoothFoundListener, BluetoothScanEndListener, BluetoothBondSuccess, BluetoothBonded, BluetoothBonding, BluetoothBondFail, Log); InitToggle(); } private void OnScan() { isScaning = !isScaning; if (isScaning) { scanText.text = "停止扫描"; connectedInfo.text = "正在扫描中..."; Input.location.Start();//定位 OnDestroyContentParent(); deviceList = new List(); FindDevice(); } else { scanText.text = "扫描"; connectedInfo.text = "扫描结束..."; BluetoothStateWrapper.Instance.StopScanBluetooth(); } } private void FindDevice() { BluetoothStateWrapper.Instance.ScanBluetooth(); } private void BluetoothScanStartListener() { } private void BluetoothFoundListener(string address, string name) { if (string.IsNullOrEmpty(name)) return; Loom.QueueOnMainThread(() => { OnInstantiateItem(address, name); }); } private void BluetoothScanEndListener() { scanText.text = "扫描"; connectedInfo.text = "扫描结束..."; isScaning = false; } private void BluetoothBondSuccess() { connectedInfo.text = "配对成功"; } private void BluetoothBonded(string address, string name) { } private void BluetoothBonding() { connectedInfo.text = "正在配对中..."; } private void BluetoothBondFail() { connectedInfo.text = "取消配对"; } private void Log(string msg) { } private void OnBond() { if (!isScaning && isInit) { isBonding = !isBonding; if (isBonding) { if (!string.IsNullOrEmpty(currentSelectedAddress)) { bondText.text = "取消配对"; BluetoothStateWrapper.Instance.BondBluetooth(currentSelectedAddress); } else { connectedInfo.text = "请选择正确的蓝牙设备"; } } else { if (!string.IsNullOrEmpty(currentSelectedAddress)) { bondText.text = "配对"; BluetoothStateWrapper.Instance.UnBondBluetooth(currentSelectedAddress); } else { connectedInfo.text = "请选择正确的蓝牙设备"; } } } } private void OnConnect() { if (!isScaning && isInit) { isConnecting = !isConnecting; if (isConnecting) { connectText.text = "断连"; connectedInfo.text = "正在连接中..."; ConnectBluetooth(); } else { connectText.text = "连接"; } } else { connectedInfo.text = "请关闭扫描,或者初始化失败"; } } private void SelectBluetooth(string address) { currentSelectedAddress = address; connectedInfo.text = $"当前地址 = {currentSelectedAddress}"; } private void ConnectBluetooth() { } private void OnDestroyContentParent() { for (int i = deviceList.Count - 1; i >= 0; i--) { int index = i; Destroy(deviceList[index].gameObject); } } private void OnInstantiateItem(string address, string name) { GameObject obj = Instantiate(Resources.Load("Item")); obj.transform.SetParent(contentParent.transform); obj.transform.localPosition = Vector3.zero; obj.transform.localScale = Vector3.one; obj.transform.GetChild(0).GetComponent().text = name; obj.GetComponent().bluetooth = this; obj.GetComponent().address = address; obj.GetComponent().btName = name; obj.GetComponent().onClick = selectBluetoothAction; deviceList.Add(obj.GetComponent()); } #region 申请权限 //申请相关 private PermissionCallbacks m_PermissionCallbacks; private StringBuilder m_StringBuilder; private bool m_IsGetAllPermission; private void RequestPermissions() { if (m_StringBuilder == null) { m_StringBuilder = new StringBuilder(); } else { m_StringBuilder.Clear(); } m_IsGetAllPermission = false; //申请回调 m_PermissionCallbacks = new PermissionCallbacks(); m_PermissionCallbacks.PermissionDenied += OnPermissionDenied; m_PermissionCallbacks.PermissionGranted += OnPermissionGranted; m_PermissionCallbacks.PermissionDeniedAndDontAskAgain += OnPermissionDeniedAndDontAskAgain; //申请权限组 string[] permissions = { "android.permission.BLUETOOTH_SCAN", "android.permission.BLUETOOTH_ADVERTISE", "android.permission.BLUETOOTH_CONNECT", // 添加其他权限 }; //执行申请多个权限 Permission.RequestUserPermissions(permissions, m_PermissionCallbacks); } /// /// 申请权限被拒绝 /// /// private void OnPermissionDenied(string permission) { Write($"OnPermissionDenied:{permission}"); } /// /// 申请权限成功 /// /// private void OnPermissionGranted(string permission) { Write($"OnPermissionGranted:{permission}"); //检查权限是否全部通过 if (Permission.HasUserAuthorizedPermission("android.permission.BLUETOOTH_SCAN") && Permission.HasUserAuthorizedPermission("android.permission.BLUETOOTH_ADVERTISE") && Permission.HasUserAuthorizedPermission("android.permission.BLUETOOTH_CONNECT")) { //一次申请多个权限,比如申请2个。会依次弹窗进行申请,在全部交互完成后才开始回调接口。如若玩家全部同意。这里会回调2次 //所以这里需要加个变量防止重复回调 if (!m_IsGetAllPermission) { m_IsGetAllPermission = true; //在这里处理权限通过的逻辑 //do something Debug.Log("权限申请通过"); } } } /// /// 申请权限被拒绝,且不再询问 /// /// private void OnPermissionDeniedAndDontAskAgain(string permission) { Write($"OnPermissionDeniedAndDontAskAgain:{permission}"); } private void Write(string str) { m_StringBuilder.AppendLine(str); connectedInfo.text = m_StringBuilder.ToString(); Debug.Log(m_StringBuilder.ToString()); } #endregion private void InitToggle() { // 获取当前状态 SetIsOnToggle(BluetoothStateWrapper.Instance.getBlueToothState()); // 设置监听事件 openBluetoothTog.onValueChanged.AddListener((isOn) => { if (isOn == true) { BluetoothStateWrapper.Instance.openBlueTooth(); } else { BluetoothStateWrapper.Instance.colseBlueTooth(); } }); BluetoothStateWrapper.Instance.GetBondedBluetooth(); } void SetOnToggle() { SetIsOnToggle(true); } void SetOffToggle() { SetIsOnToggle(false); } void SetIsOnToggle(bool isOn) { openBluetoothTog.isOn = isOn; }}
AndroidManifest:
上一篇:案件管理系统的核心功能与优势解析