简体   繁体   English

Flutter 连接 Package:Android 权限

[英]Flutter Connectivity Package: Android Permissions

I'm using the sample code from https://pub.dev/packages/connectivity#-example-tab- in a Flutter application and when running the application on an Android emulator, the app sees the debug wi-fi network.我在 Flutter 应用程序中使用来自https://pub.dev/packages/connectivity#-example-tab-的示例代码,并且在 Android 应用程序上运行应用程序时,请参阅调试程序网络。 However, when I run the app on my Pixel 4XL, I get null for wi-fi name and BSSID.但是,当我在我的 Pixel 4XL 上运行该应用程序时,我会得到 null 以获取 Wi-Fi 名称和 BSSID。

I'm assuming I have to enable permissions to access Wi-Fi settings to use this package, but I can't find any reference anywhere that describes what's required for this package on Flutter.我假设我必须启用访问 Wi-Fi 设置的权限才能使用此 package,但我在任何地方都找不到任何参考资料来描述 ZC047B10EEE761CC264C078 上此 package 所需的内容

I updated the Android app appmanifest file with the wi-fi permissions from the wi-fi package example, but nothing changed in my app.我使用 Wi-Fi package 示例中的 Wi-Fi 权限更新了 Android 应用程序 appmanifest 文件,但我的应用程序没有任何变化。

I created a sample app that demonstrated the solution but apparently the Stack Overflow folks want me to work even harder to share this information with you.我创建了一个示例应用程序来演示解决方案,但显然 Stack Overflow 的人们希望我更加努力地与您分享这些信息。 They deleted my original answer (even though it solved the problem for everyone who had the issue).他们删除了我原来的答案(尽管它为每个有问题的人解决了问题)。 And want me to pull out parts of the answer and post them here.并希望我提取部分答案并将其张贴在这里。 I did a lot of work to solve this issue and publish it as a complete app sample, but apparently that's not enough.我做了很多工作来解决这个问题并将它作为一个完整的应用程序示例发布,但显然这还不够。 I hate this.我讨厌这个。 I'm trying to help people but they don't like external references to the solution.我正在尝试帮助人们,但他们不喜欢对解决方案的外部引用。

I created a complete solution that demonstrates how to solve this problem in https://github.com/johnwargo/flutter-android-connectivity-permissions .我创建了一个完整的解决方案来演示如何在https://github.com/johnwargo/flutter-android-connectivity-permissions中解决这个问题。

Flutter doesn't seem to have a way to query an app user for permissions, so someone created the Flutter permissions_handler package. Flutter 似乎没有办法查询应用程序用户的权限,所以有人创建了 Flutter permissions_handler package。 Adding that to my app, and a variant of the code shown in the original issue, solved my issue.将它添加到我的应用程序以及原始问题中显示的代码变体解决了我的问题。

I quickly realized that the answer on the Flutter repo was incomplete and anyone trying to implement this solution would need some help.我很快意识到 Flutter repo 上的答案是不完整的,任何尝试实施此解决方案的人都需要一些帮助。 To make it easier for these developers, I created a complete sample application here in this repo.为了让这些开发人员更容易,我在这个 repo 中创建了一个完整的示例应用程序。

Here's what I did这就是我所做的

Starting with the project's pubspec.yaml file, I added the connectivity and permissions_handler packages:从项目的pubspec.yaml文件开始,我添加了连接和权限处理程序包:

dependencies:
  flutter:
    sdk: flutter

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

Next, I added the imports to the project's main.dart file:接下来,我将导入添加到项目的main.dart文件中:

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

Then I added some code to the initConnectivity function:然后我在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);
}

The code I added is:我添加的代码是:

// 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?)');
  }
}

This code executes once at startup and checks permissions before retrieving connection status from the device.此代码在启动时执行一次,并在从设备检索连接状态之前检查权限。

If you run the code at this point, everything will seem to work, but the values for Wi-Fi Name, BSSID and IP address will all report null .如果此时运行代码,似乎一切正常,但 Wi-Fi 名称、BSSID 和 IP 地址的值都会报告null When you look at the console, you'll see:当您查看控制台时,您会看到:

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

That's because without the right permissions defined within the app, the status value is null and none of the other permissions checking stuff happens.这是因为如果没有在应用程序中定义正确的权限, status值为null并且不会发生其他权限检查。 The user is never even asked for permission as expected.甚至从未像预期的那样要求用户许可。

To solve this, open the project's android/app/src/main/AndroidManifest.xml file and add the location permission to the app's config:要解决这个问题,请打开项目的android/app/src/main/AndroidManifest.xml文件并将位置权限添加到应用程序的配置中:

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

I used the course setting, you can use the fine too I think.我使用了课程设置,我认为您也可以使用罚款。

So many times writers tell you what permission change to make, but don't tell you where it should be made in the file.很多时候,作者会告诉您要进行哪些权限更改,但没有告诉您应该在文件中的哪个位置进行更改。 I don't do a lot of native Android development, so I'm never sure where to put that setting, so here's the complete file listing so you can see its proper place:我没有做很多原生 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>

When you launch the app on Android API 29, it looks like this:当您在 Android API 29 上启动应用程序时,它看起来像这样:

For my particular app I don't care about getting settings from the device when the app isn't running, so I selected 'Allow only when using the app`.对于我的特定应用程序,我不关心在应用程序未运行时从设备获取设置,因此我选择了“仅在使用应用程序时允许”。 If you look in the console, you'll see the following:如果您查看控制台,您将看到以下内容:

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

Notice the app goes ahead and checks Wi-Fi settings while it waits for the user to grant permission;请注意,该应用程序会在等待用户授予权限时继续检查 Wi-Fi 设置; that's because of the way the code is written, you could easily tweak this so it waits for permission before trying, but it runs the init twice, so you'll get the right data the second time around (no, I don't know why it runs twice).那是因为代码的编写方式,您可以轻松地对其进行调整,以便在尝试之前等待许可,但它会运行两次 init,因此您将第二次获得正确的数据(不,我不知道为什么它运行两次)。

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

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