Unity Android 之 获取蓝牙Bluetooth 的状态,设置的蓝牙Bluetooth 的开关状态,并监听蓝牙Bluetooth 的状态变化方法整理

约定不等于承诺〃 2022-11-30 15:58 991阅读 0赞

20200825111221117.png

Unity Android 之 获取蓝牙Bluetooth 的状态,设置的蓝牙Bluetooth 的开关状态,并监听蓝牙Bluetooth 的状态变化方法整理

目录

Unity Android 之 获取蓝牙Bluetooth 的状态,设置的蓝牙Bluetooth 的开关状态,并监听蓝牙Bluetooth 的状态变化方法整理

一、简单介绍

二、实现原理

三、注意事项

四、效果预览

五、实现步骤

Android 端:

Unity 端

六、关键代码

Android 端

Unity 端


一、简单介绍

Unity Android 开发上会用到的技术简单整理,方便自己日后查看,能帮助到大家就更好了。

本节介绍,Unity 开发中,把从 Android 获取手机设备的蓝牙Bluetooth的状态,并设置蓝牙Bluetooth开关,监听蓝牙Bluetooth的状态变化的方法整理封装给Unity调用,方法不唯一,欢迎指正。

二、实现原理

1、获取蓝牙适配器 BluetoothAdapter.getDefaultAdapter()

2、bluetoothAdapter.isEnabled() 获取蓝牙的状态

3、bluetoothAdapter.enable()/bluetoothAdapter.disable() 设置蓝牙开关状态

4、使用广播监听 BluetoothAdapter.ACTION_STATE_CHANGED 蓝牙状态变化

5、打包成 aar ,Unity 调用 aar 的封装好的接口

三、注意事项

1、添加蓝牙权限

四、效果预览

20200825112206219.gif

五、实现步骤

Android 端:

1、新建一个Android Library 模块,其他默认设置就好

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQzNjEyODA_size_16_color_FFFFFF_t_70

2、在模块中新建两个脚本,BluetoothStateUtil 封装各个功能,BluetoothStateInterface 一个接口函数,蓝牙状态变化的接口

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQzNjEyODA_size_16_color_FFFFFF_t_70 1

3、脚本编辑 OK,Build - Make Module ‘xxxx’,打包 aar

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQzNjEyODA_size_16_color_FFFFFF_t_70 2

4、打包成功,build 文件夹outputs/aar中就会 有对应的 aar 生成

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQzNjEyODA_size_16_color_FFFFFF_t_70 3

Unity 端

1、把 Android 打包的 aar 导入 Unity

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQzNjEyODA_size_16_color_FFFFFF_t_70 4

2、在场景中布局UI,Toggle 显示设置 蓝牙状态

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQzNjEyODA_size_16_color_FFFFFF_t_70 5

3、在 Unity工程中,新建脚本,编辑对应功能

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQzNjEyODA_size_16_color_FFFFFF_t_70 6

4、把 TestBluetoothStateWrapper 挂载到场景中,并对应赋值

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQzNjEyODA_size_16_color_FFFFFF_t_70 7

5、运行场景,没有问题,即可打包到真机上测试

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQzNjEyODA_size_16_color_FFFFFF_t_70 8

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQzNjEyODA_size_16_color_FFFFFF_t_70 9

6、真机上的测试效果如上

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQzNjEyODA_size_16_color_FFFFFF_t_70 10

六、关键代码

Android 端

1、BluetoothStateUtil

  1. package com.example.bluetoothstatewrapper;
  2. import android.app.Activity;
  3. import android.bluetooth.BluetoothAdapter;
  4. import android.bluetooth.BluetoothDevice;
  5. import android.content.BroadcastReceiver;
  6. import android.content.Context;
  7. import android.content.Intent;
  8. import android.content.IntentFilter;
  9. import android.util.Log;
  10. import android.widget.Toast;
  11. public class BluetoothStateUtil {
  12. private static final String TAG = "Main_BluetoothStateUtil";
  13. private BluetoothAdapter bluetoothAdapter;
  14. private BluetoothStateBroadcastReceive mReceive;
  15. private Context mContext;
  16. private BluetoothStateInterface mBluetoothStateInterface;
  17. /**
  18. * 初始化
  19. */
  20. public void Init(BluetoothStateInterface bluetoothStateInterface){
  21. // 获得蓝牙适配器对象
  22. bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
  23. mContext = getActivity();
  24. mBluetoothStateInterface = bluetoothStateInterface;
  25. }
  26. /**
  27. * 获取蓝牙状态
  28. * @return
  29. */
  30. public boolean getBlueToothState() {
  31. // 获取蓝牙状态
  32. return bluetoothAdapter.isEnabled();
  33. }
  34. /**
  35. * 开启蓝牙
  36. * @return
  37. */
  38. public boolean openBlueTooth() {
  39. if (getBlueToothState()) return true;
  40. // 打开蓝牙
  41. return bluetoothAdapter.enable();
  42. }
  43. /**
  44. * 关闭蓝牙
  45. * @return
  46. */
  47. public boolean colseBlueTooth() {
  48. if (!getBlueToothState()) return true;
  49. // 关闭蓝牙
  50. return bluetoothAdapter.disable();
  51. }
  52. // 调用系统的请求打开蓝牙
  53. public void gotoSystem(Context context){
  54. Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
  55. context.startActivity(intent);
  56. }
  57. /**
  58. * 注册监听蓝牙变化
  59. */
  60. public void registerBluetoothReceiver(){
  61. if(mReceive == null){
  62. mReceive = new BluetoothStateBroadcastReceive();
  63. }
  64. IntentFilter intentFilter = new IntentFilter();
  65. intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
  66. intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
  67. intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
  68. intentFilter.addAction("android.bluetooth.BluetoothAdapter.STATE_OFF");
  69. intentFilter.addAction("android.bluetooth.BluetoothAdapter.STATE_ON");
  70. mContext.registerReceiver(mReceive, intentFilter);
  71. }
  72. /**
  73. * 取消监听蓝牙变化
  74. */
  75. public void unregisterBluetoothReceiver(){
  76. if(mReceive != null){
  77. mContext.unregisterReceiver(mReceive);
  78. mReceive = null;
  79. }
  80. }
  81. /**
  82. * 蓝牙状态变化监听
  83. */
  84. class BluetoothStateBroadcastReceive extends BroadcastReceiver {
  85. @Override
  86. public void onReceive(Context context, Intent intent) {
  87. String action = intent.getAction();
  88. BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
  89. switch (action){
  90. case BluetoothDevice.ACTION_ACL_CONNECTED:
  91. //Toast.makeText(context , "蓝牙设备:" + device.getName() + "已连接", Toast.LENGTH_SHORT).show();
  92. Log.i(TAG, "onReceive: "+"蓝牙设备:" + device.getName() + "已连接");
  93. break;
  94. case BluetoothDevice.ACTION_ACL_DISCONNECTED:
  95. //Toast.makeText(context , "蓝牙设备:" + device.getName() + "已断开", Toast.LENGTH_SHORT).show();
  96. Log.i(TAG, "onReceive: "+"蓝牙设备:" + device.getName() + "已断开");
  97. break;
  98. case BluetoothAdapter.ACTION_STATE_CHANGED:
  99. int blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
  100. switch (blueState){
  101. case BluetoothAdapter.STATE_OFF:
  102. //Toast.makeText(context , "蓝牙已关闭", Toast.LENGTH_SHORT).show();
  103. Log.i(TAG, "onReceive: "+"蓝牙已关闭:" );
  104. mBluetoothStateInterface.onBluetoothStateOFF();
  105. break;
  106. case BluetoothAdapter.STATE_ON:
  107. //Toast.makeText(context , "蓝牙已开启" , Toast.LENGTH_SHORT).show();
  108. Log.i(TAG, "onReceive: "+"蓝牙已开启:");
  109. mBluetoothStateInterface.onBluetoothStateON();
  110. break;
  111. }
  112. break;
  113. }
  114. }
  115. }
  116. // 设置一个 Activity 参数
  117. private Activity _unityActivity;
  118. // 通过反射获取 Unity 的 Activity 的上下文
  119. Activity getActivity(){
  120. if(null == _unityActivity){
  121. try{
  122. Class<?> classtype = Class.forName("com.unity3d.player.UnityPlayer");
  123. Activity activity = (Activity) classtype.getDeclaredField("currentActivity").get(classtype);
  124. _unityActivity = activity;
  125. }catch (ClassNotFoundException e){
  126. e.printStackTrace();
  127. }catch (IllegalAccessException e){
  128. e.printStackTrace();
  129. }catch (NoSuchFieldException e){
  130. e.printStackTrace();
  131. }
  132. }
  133. return _unityActivity;
  134. }
  135. }

2、BluetoothStateInterface

  1. package com.example.bluetoothstatewrapper;
  2. public interface BluetoothStateInterface {
  3. void onBluetoothStateON();
  4. void onBluetoothStateOFF();
  5. }

3、AndroidManifest.xml

  1. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  2. package="com.example.bluetoothstatewrapper" >
  3. <uses-permission android:name="android.permission.BLUETOOTH"/>
  4. <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
  5. </manifest>

Unity 端

1、BluetoothStateWrapper

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. namespace AndroidWrapper {
  6. /// <summary>
  7. /// 蓝牙状态封装
  8. /// 使用说明
  9. /// 1、首先初始化,绑定监听事件
  10. /// 2、可获取蓝牙状态,设置蓝牙状态
  11. /// 3、获得监听结果
  12. /// </summary>
  13. public class BluetoothStateWrapper : MonoSingleton<BluetoothStateWrapper>
  14. {
  15. /// <summary>
  16. /// 初始化
  17. /// </summary>
  18. /// <param name="VoiceVolumnChangedListener"></param>
  19. public void Init(Action OnBluetoothStateONListener, Action OnBluetoothStateOFFListener)
  20. {
  21. #if UNITY_EDITOR
  22. #else
  23. MAndroidJavaObject.Call("Init",new BluetoothStateInterface(OnBluetoothStateONListener, OnBluetoothStateOFFListener));
  24. registerBluetoothReceiver();
  25. #endif
  26. }
  27. /// <summary>
  28. /// 获得蓝牙状态
  29. /// </summary>
  30. /// <returns></returns>
  31. public bool getBlueToothState()
  32. {
  33. return MAndroidJavaObject.Call<bool>("getBlueToothState");
  34. }
  35. /// <summary>
  36. /// 开启蓝牙
  37. /// </summary>
  38. /// <returns></returns>
  39. public bool openBlueTooth()
  40. {
  41. return MAndroidJavaObject.Call<bool>("openBlueTooth");
  42. }
  43. /// <summary>
  44. /// 关闭蓝牙
  45. /// </summary>
  46. /// <returns></returns>
  47. public bool colseBlueTooth()
  48. {
  49. return MAndroidJavaObject.Call<bool>("colseBlueTooth");
  50. }
  51. #region 私有方法
  52. /// <summary>
  53. /// 注册蓝牙状态监听
  54. /// </summary>
  55. void registerBluetoothReceiver()
  56. {
  57. MAndroidJavaObject.Call("registerBluetoothReceiver");
  58. }
  59. /// <summary>
  60. /// 取消注册蓝牙状态监听
  61. /// </summary>
  62. void unregisterBluetoothReceiver()
  63. {
  64. MAndroidJavaObject.Call("unregisterBluetoothReceiver");
  65. }
  66. protected override void OnDestroy()
  67. {
  68. unregisterBluetoothReceiver();
  69. base.OnDestroy();
  70. }
  71. #endregion
  72. #region 私有变量
  73. AndroidJavaObject _mAndroidJavaObject;
  74. public AndroidJavaObject MAndroidJavaObject
  75. {
  76. get
  77. {
  78. if (_mAndroidJavaObject == null)
  79. {
  80. _mAndroidJavaObject = new AndroidJavaObject("com.example.bluetoothstatewrapper.BluetoothStateUtil");
  81. }
  82. return _mAndroidJavaObject;
  83. }
  84. }
  85. #endregion
  86. }
  87. }

2、BluetoothStateInterface

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. namespace AndroidWrapper
  6. {
  7. /// <summary>
  8. /// 蓝牙状态监听接口
  9. /// </summary>
  10. public class BluetoothStateInterface : AndroidJavaProxy
  11. {
  12. /// <summary>
  13. /// 蓝牙变化委托事件
  14. /// </summary>
  15. Action _mBluetoothStateON;
  16. Action _mBluetoothStateOFF;
  17. public BluetoothStateInterface(Action mBluetoothStateON, Action mBluetoothStateOFF) : base("com.example.bluetoothstatewrapper.BluetoothStateInterface")
  18. {
  19. _mBluetoothStateON = mBluetoothStateON;
  20. _mBluetoothStateOFF = mBluetoothStateOFF;
  21. }
  22. /// <summary>
  23. /// 蓝牙打开事件监听
  24. /// </summary>
  25. public void onBluetoothStateON()
  26. {
  27. if (_mBluetoothStateON != null)
  28. {
  29. _mBluetoothStateON();
  30. }
  31. Debug.Log(GetType() + "/onBluetoothStateON()/ 蓝牙开启事件");
  32. }
  33. /// <summary>
  34. /// 蓝牙关闭事件监听
  35. /// </summary>
  36. public void onBluetoothStateOFF()
  37. {
  38. if (_mBluetoothStateOFF != null)
  39. {
  40. _mBluetoothStateOFF();
  41. }
  42. Debug.Log(GetType() + "/onBluetoothStateOFF()/ 蓝牙关闭事件");
  43. }
  44. }
  45. }

3、TestBluetoothStateWrapper

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using AndroidWrapper;
  5. using UnityEngine.UI;
  6. public class TestBluetoothStateWrapper : MonoBehaviour
  7. {
  8. public Toggle BTState_Toggle;
  9. // Start is called before the first frame update
  10. void Start()
  11. {
  12. BluetoothStateWrapper.Instance.Init(SetOnToggle, SetOffToggle);
  13. InitToggle();
  14. }
  15. /// <summary>
  16. /// 初始化
  17. /// </summary>
  18. void InitToggle() {
  19. #if UNITY_EDITOR
  20. // 获取当前状态
  21. SetIsOnToggle(Random.Range(0,2) ==0 ? false:true);
  22. // 设置监听事件
  23. BTState_Toggle.onValueChanged.AddListener((isOn) => {
  24. });
  25. #else
  26. // 获取当前状态
  27. SetIsOnToggle(BluetoothStateWrapper.Instance.getBlueToothState());
  28. // 设置监听事件
  29. BTState_Toggle.onValueChanged.AddListener((isOn)=> {
  30. if (isOn == true)
  31. {
  32. BluetoothStateWrapper.Instance.openBlueTooth();
  33. }
  34. else {
  35. BluetoothStateWrapper.Instance.colseBlueTooth();
  36. }
  37. });
  38. #endif
  39. }
  40. void SetOnToggle() {
  41. SetIsOnToggle(true);
  42. }
  43. void SetOffToggle()
  44. {
  45. SetIsOnToggle(false);
  46. }
  47. void SetIsOnToggle(bool isOn) {
  48. BTState_Toggle.isOn = isOn;
  49. }
  50. }

4、MonoSingleton

  1. using UnityEngine;
  2. public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoBehaviour
  3. {
  4. private static T instance = null;
  5. private static readonly object locker = new object();
  6. private static bool bAppQuitting;
  7. public static T Instance
  8. {
  9. get
  10. {
  11. if (bAppQuitting)
  12. {
  13. instance = null;
  14. return instance;
  15. }
  16. lock (locker)
  17. {
  18. if (instance == null)
  19. {
  20. instance = FindObjectOfType<T>();
  21. if (FindObjectsOfType<T>().Length > 1)
  22. {
  23. Debug.LogError("不应该存在多个单例!");
  24. return instance;
  25. }
  26. if (instance == null)
  27. {
  28. var singleton = new GameObject();
  29. instance = singleton.AddComponent<T>();
  30. singleton.name = "(singleton)" + typeof(T);
  31. singleton.hideFlags = HideFlags.None;
  32. DontDestroyOnLoad(singleton);
  33. }
  34. else
  35. DontDestroyOnLoad(instance.gameObject);
  36. }
  37. instance.hideFlags = HideFlags.None;
  38. return instance;
  39. }
  40. }
  41. }
  42. protected virtual void Awake()
  43. {
  44. bAppQuitting = false;
  45. }
  46. protected virtual void OnDestroy()
  47. {
  48. bAppQuitting = true;
  49. }
  50. }

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQzNjEyODA_size_16_color_FFFFFF_t_70 11

发表评论

表情:
评论列表 (有 0 条评论,991人围观)

还没有评论,来说两句吧...

相关阅读