繁体   English   中英

Flutter 连接 Package:Android 权限

[英]Flutter Connectivity Package: Android Permissions

我在 Flutter 应用程序中使用来自https://pub.dev/packages/connectivity#-example-tab-的示例代码,并且在 Android 应用程序上运行应用程序时,请参阅调试程序网络。 但是,当我在我的 Pixel 4XL 上运行该应用程序时,我会得到 null 以获取 Wi-Fi 名称和 BSSID。

我假设我必须启用访问 Wi-Fi 设置的权限才能使用此 package,但我在任何地方都找不到任何参考资料来描述 ZC047B10EEE761CC264C078 上此 package 所需的内容

我使用 Wi-Fi package 示例中的 Wi-Fi 权限更新了 Android 应用程序 appmanifest 文件,但我的应用程序没有任何变化。

我创建了一个示例应用程序来演示解决方案,但显然 Stack Overflow 的人们希望我更加努力地与您分享这些信息。 他们删除了我原来的答案(尽管它为每个有问题的人解决了问题)。 并希望我提取部分答案并将其张贴在这里。 我做了很多工作来解决这个问题并将它作为一个完整的应用程序示例发布,但显然这还不够。 我讨厌这个。 我正在尝试帮助人们,但他们不喜欢对解决方案的外部引用。

我创建了一个完整的解决方案来演示如何在https://github.com/johnwargo/flutter-android-connectivity-permissions中解决这个问题。

Flutter 似乎没有办法查询应用程序用户的权限,所以有人创建了 Flutter permissions_handler package。 将它添加到我的应用程序以及原始问题中显示的代码变体解决了我的问题。

我很快意识到 Flutter repo 上的答案是不完整的,任何尝试实施此解决方案的人都需要一些帮助。 为了让这些开发人员更容易,我在这个 repo 中创建了一个完整的示例应用程序。

这就是我所做的

从项目的pubspec.yaml文件开始,我添加了连接和权限处理程序包:

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^0.1.3
  connectivity: ^0.4.8+6  
  permission_handler: ^5.0.1

接下来,我将导入添加到项目的main.dart文件中:

import 'package:connectivity/connectivity.dart';
import 'package:permission_handler/permission_handler.dart';

然后我在initConnectivity function 中添加了一些代码:

Future<void> initConnectivity() async {
  ConnectivityResult result;
  // Platform messages may fail, so we use a try/catch PlatformException.
  try {
    result = await _connectivity.checkConnectivity();
  } on PlatformException catch (e) {
    print(e.toString());
  }

  // If the widget was removed from the tree while the asynchronous platform
  // message was in flight, we want to discard the reply rather than calling
  // setState to update our non-existent appearance.
  if (!mounted) {
    return Future.value(null);
  }

  // Check to see if Android Location permissions are enabled
  // Described in https://github.com/flutter/flutter/issues/51529
  if (Platform.isAndroid) {
    print('Checking Android permissions');
    var status = await Permission.location.status;
    // Blocked?
    if (status.isUndetermined || status.isDenied || status.isRestricted) {
      // Ask the user to unblock
      if (await Permission.location.request().isGranted) {
        // Either the permission was already granted before or the user just granted it.
        print('Location permission granted');
      } else {
        print('Location permission not granted');
      }
    } else {
      print('Permission already granted (previous execution?)');
    }
  }

  return _updateConnectionStatus(result);
}

我添加的代码是:

// Check to see if Android Location permissions are enabled
// Described in https://github.com/flutter/flutter/issues/51529
if (Platform.isAndroid) {
  print('Checking Android permissions');
  var status = await Permission.location.status;
  // Blocked?
  if (status.isUndetermined || status.isDenied || status.isRestricted) {
    // Ask the user to unblock
    if (await Permission.location.request().isGranted) {
      // Either the permission was already granted before or the user just granted it.
      print('Location permission granted');
    } else {
      print('Location permission not granted');
    }
  } else {
    print('Permission already granted (previous execution?)');
  }
}

此代码在启动时执行一次,并在从设备检索连接状态之前检查权限。

如果此时运行代码,似乎一切正常,但 Wi-Fi 名称、BSSID 和 IP 地址的值都会报告null 当您查看控制台时,您会看到:

I/flutter ( 6506): Checking Android permissions
I/flutter ( 6506): Result: ConnectivityResult.wifi
D/permissions_handler( 6506): No permissions found in manifest for: 3
I/flutter ( 6506): Wi-Fi Name: null
D/permissions_handler( 6506): No permissions found in manifest for: 3
I/flutter ( 6506): Location permission not granted
I/flutter ( 6506): Result: ConnectivityResult.wifi
I/flutter ( 6506): BSSID: 02:00:00:00:00:00
I/flutter ( 6506): Wi-Fi Name: null
I/flutter ( 6506): BSSID: 02:00:00:00:00:00

这是因为如果没有在应用程序中定义正确的权限, status值为null并且不会发生其他权限检查。 甚至从未像预期的那样要求用户许可。

要解决这个问题,请打开项目的android/app/src/main/AndroidManifest.xml文件并将位置权限添加到应用程序的配置中:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

我使用了课程设置,我认为您也可以使用罚款。

很多时候,作者会告诉您要进行哪些权限更改,但没有告诉您应该在文件中的哪个位置进行更改。 我没有做很多原生 Android 开发,所以我不知道该设置在哪里,所以这里是完整的文件列表,所以你可以看到它的正确位置:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.johnwargo.connectivitypermissions">
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <application
        android:name="io.flutter.app.FlutterApplication"
        android:label="connectivitypermissions"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data
              android:name="io.flutter.embedding.android.NormalTheme"
              android:resource="@style/NormalTheme"
              />
            <!-- Displays an Android View that continues showing the launch screen
                 Drawable until Flutter paints its first frame, then this splash
                 screen fades out. A splash screen is useful to avoid any visual
                 gap between the end of Android's launch screen and the painting of
                 Flutter's first frame. -->
            <meta-data
              android:name="io.flutter.embedding.android.SplashScreenDrawable"
              android:resource="@drawable/launch_background"
              />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
</manifest>

当您在 Android API 29 上启动应用程序时,它看起来像这样:

对于我的特定应用程序,我不关心在应用程序未运行时从设备获取设置,因此我选择了“仅在使用应用程序时允许”。 如果您查看控制台,您将看到以下内容:

I/flutter ( 7670): Checking Android permissions
I/flutter ( 7670): Result: ConnectivityResult.wifi
I/flutter ( 7670): Wi-Fi Name: null
I/flutter ( 7670): BSSID: 02:00:00:00:00:00
I/flutter ( 7670): Location permission granted
I/flutter ( 7670): Result: ConnectivityResult.wifi
I/flutter ( 7670): Wi-Fi Name: AndroidWifi
I/flutter ( 7670): BSSID: 02:15:b2:00:01:00

请注意,该应用程序会在等待用户授予权限时继续检查 Wi-Fi 设置; 那是因为代码的编写方式,您可以轻松地对其进行调整,以便在尝试之前等待许可,但它会运行两次 init,因此您将第二次获得正确的数据(不,我不知道为什么它运行两次)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM