flutter 完美處理iOS Android兩端藍牙權限,解決Android12藍牙掃描崩潰

前言

最近在做一個配置工具,給Zigbee網(wǎng)關配置網(wǎng)絡的工具,其中有一個環(huán)節(jié),是用藍牙配置,過程遇到權限各種坑,故有此篇文章,其中我們使用了第三方庫permission_handler,而且permission_handler版本要大于8.2.0才行。

image.png

Android端

第一步:工程名稱/android/app/src/main/AndroidManifest.xml,下添加以下權限
image.png

代碼如下:

    <uses-permission android:name="android.permission.INTERNET" />
    <!-- Request legacy Bluetooth permissions on older devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH"
        android:maxSdkVersion="30" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
        android:maxSdkVersion="30" />

    <!-- Needed only if your app looks for Bluetooth devices.
         You must add an attribute to this permission, or declare the
         ACCESS_FINE_LOCATION permission, depending on the results when you
         check location usage in your app. -->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />

    <!-- Needed only if your app makes the device discoverable to Bluetooth
         devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />

    <!-- Needed only if your app communicates with already-paired Bluetooth
         devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

在Android12之前的版本,只需要授權位置權限,下面這些都是PermissionStatus.granted

    var isLocationGranted = await Permission.locationWhenInUse.request();
    print('checkBlePermissions, isLocationGranted=$isLocationGranted');


    var isBleGranted = await Permission.bluetooth.request();
    print('checkBlePermissions, isBleGranted=$isBleGranted');

    var isBleScanGranted = await Permission.bluetoothScan.request();
    print('checkBlePermissions, isBleScanGranted=$isBleScanGranted');
    //
    var isBleConnectGranted = await Permission.bluetoothConnect.request();
    print('checkBlePermissions, isBleConnectGranted=$isBleConnectGranted');
    //
    var isBleAdvertiseGranted = await Permission.bluetoothAdvertise.request();
    print('checkBlePermissions, isBleAdvertiseGranted=$isBleAdvertiseGranted');

在>=Android12的版本,除了需要授權“位置權限”,還需要授權“使用附近的設備權限” ,下面這些才會都是PermissionStatus.granted,藍牙才能正常使用起來

    var isBleScanGranted = await Permission.bluetoothScan.request();
    print('checkBlePermissions, isBleScanGranted=$isBleScanGranted');
    //
    var isBleConnectGranted = await Permission.bluetoothConnect.request();
    print('checkBlePermissions, isBleConnectGranted=$isBleConnectGranted');
    //
    var isBleAdvertiseGranted = await Permission.bluetoothAdvertise.request();
    print('checkBlePermissions, isBleAdvertiseGranted=$isBleAdvertiseGranted');

需要注意的是:在>=Android12的版本, var isBleGranted = await Permission.bluetooth.request();默認為PermissionStatus.denied,應該是因為使用了上面3個權限代替了

第二步,動態(tài)申請權限最終代碼

其中投機取巧了一下

  Future<bool> requestBlePermissions() async {
    location.Location _location = new location.Location();
    bool _serviceEnabled;

    _serviceEnabled = await _location.serviceEnabled();
    if (!_serviceEnabled) {
      _serviceEnabled = await _location.requestService();
      if (!_serviceEnabled) {
        return false;
      }
    }
    var isLocationGranted = await Permission.locationWhenInUse.request();
    print('checkBlePermissions, isLocationGranted=$isLocationGranted');


    var isBleGranted = await Permission.bluetooth.request();
    print('checkBlePermissions, isBleGranted=$isBleGranted');

    var isBleScanGranted = await Permission.bluetoothScan.request();
    print('checkBlePermissions, isBleScanGranted=$isBleScanGranted');
    //
    var isBleConnectGranted = await Permission.bluetoothConnect.request();
    print('checkBlePermissions, isBleConnectGranted=$isBleConnectGranted');
    //
    var isBleAdvertiseGranted = await Permission.bluetoothAdvertise.request();
    print('checkBlePermissions, isBleAdvertiseGranted=$isBleAdvertiseGranted');

    if(Platform.isIOS) {
      return isBleGranted == PermissionStatus.granted;

    }else {
      return isLocationGranted == PermissionStatus.granted &&
           // isBleGranted == PermissionStatus.granted  &&
          isBleScanGranted == PermissionStatus.granted &&
          isBleConnectGranted == PermissionStatus.granted &&
          isBleAdvertiseGranted == PermissionStatus.granted;
    }
  }

iOS端

第一步:info.plist文件申請
image.png
第二步:增加后臺模式權限
image.png

如下圖所示,選中


image.png
第三步:Podfile文件里面添加代碼
image.png

代碼如下:

    target.build_configurations.each do |config|
      config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
        '$(inherited)',
        # dart: [PermissionGroup. location, PermissionGroup. locationAlways, PermissionGroup. locationWhenInUse]
        'PERMISSION_LOCATION=1',
        ## dart: PermissionGroup.bluetooth
        'PERMISSION_BLUETOOTH=1',
      ]
    end
第四步:Podfile文件里面添加代碼后,需要重新pod install,安裝一下,才會產(chǎn)生效果
第五步:在代碼里面調(diào)用藍牙權限
image.png
  Future<bool> requestBlePermissions() async {
    location.Location _location = new location.Location();
    bool _serviceEnabled;

    _serviceEnabled = await _location.serviceEnabled();
    if (!_serviceEnabled) {
      _serviceEnabled = await _location.requestService();
      if (!_serviceEnabled) {
        return false;
      }
    }
    var isLocationGranted = await Permission.locationWhenInUse.request();
    print('checkBlePermissions, isLocationGranted=$isLocationGranted');


    var isBleGranted = await Permission.bluetooth.request();
    print('checkBlePermissions, isBleGranted=$isBleGranted');

    var isBleScanGranted = await Permission.bluetoothScan.request();
    print('checkBlePermissions, isBleScanGranted=$isBleScanGranted');
    //
    var isBleConnectGranted = await Permission.bluetoothConnect.request();
    print('checkBlePermissions, isBleConnectGranted=$isBleConnectGranted');
    //
    var isBleAdvertiseGranted = await Permission.bluetoothAdvertise.request();
    print('checkBlePermissions, isBleAdvertiseGranted=$isBleAdvertiseGranted');

    if(Platform.isIOS) {
      return isBleGranted == PermissionStatus.granted;

    }else {
      return isLocationGranted == PermissionStatus.granted &&
           // isBleGranted == PermissionStatus.granted  &&
          isBleScanGranted == PermissionStatus.granted &&
          isBleConnectGranted == PermissionStatus.granted &&
          isBleAdvertiseGranted == PermissionStatus.granted;
    }
  }
最終效果

兩端都可以彈框出來申請權限,授受后,可以正常使用起來,還適配了Android12,
如果沒有適配Android12的代碼,一開始藍牙掃描,app就會崩潰

結尾

今天flutter 相關技術的分享就到這里嘍,小伴們,覺得有點用的話,或者已經(jīng)看到這里面來的請點贊加關注吧~~ 后續(xù)分享更多有關flutter及移動端原生相關文章。如果有疑問的話,請在下方留言~

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容