Flutter 连接包:Android 权限
Flutter Connectivity Package: Android Permissions
我在 Flutter 应用程序中使用 https://pub.dev/packages/connectivity#-example-tab- 中的示例代码,当 运行 在 Android 模拟器上运行该应用程序时,该应用程序会看到调试 Wi-Fi 网络.但是,当我 运行 我的 Pixel 4XL 上的应用程序时,我得到的 wi-fi 名称和 BSSID 为空。
我假设我必须启用访问 Wi-Fi 设置的权限才能使用此包,但我无法在任何地方找到描述此包在 Flutter 上的要求的任何参考资料。
我使用 wi-fi 包示例中的 wi-fi 权限更新了 Android 应用程序 appmanifest 文件,但我的应用程序没有任何变化。
我创建了一个演示解决方案的示例应用程序,但显然 Stack Overflow 的人们希望我更加努力地与您分享这些信息。他们删除了我原来的答案(即使它解决了所有有问题的人的问题)。并希望我提取部分答案并在此处 post。我做了很多工作来解决这个问题并将其作为完整的应用程序示例发布,但显然这还不够。我讨厌这个。我正在努力帮助人们,但他们不喜欢对解决方案的外部引用。
我创建了一个完整的解决方案,演示了如何解决 https://github.com/johnwargo/flutter-android-connectivity-permissions 中的这个问题。
Flutter 似乎无法查询应用程序用户的权限,因此有人创建了 Flutter permissions_handler 包。将其添加到我的应用程序,以及原始问题中显示的代码变体,解决了我的问题。
我很快意识到 Flutter 存储库上的答案不完整,任何试图实施此解决方案的人都需要一些帮助。为了方便这些开发人员,我在此存储库中创建了一个完整的示例应用程序。
这是我所做的
从项目的 pubspec.yaml
文件开始,我添加了连接和 permissions_handler 包:
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
函数中添加了一些代码:
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
并且会发生其他权限检查内容的 none。甚至从未像预期的那样要求用户获得许可。
要解决此问题,请打开项目的 android/app/src/main/AndroidManifest.xml
文件并将位置权限添加到应用程序的配置中:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
我用的是course设置,我觉得你也可以用fine
很多时候,作者会告诉您要更改什么权限,但不会告诉您应该在文件中的什么位置进行更改。我没有做很多本机 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 启动应用程序时,它看起来像这样:
对于我的特定应用程序,当应用程序未 运行ning 时,我不关心从设备获取设置,因此我选择了“仅在使用该应用程序时允许”。如果您查看控制台,您将看到以下内容:
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 设置;那是因为代码的编写方式,你可以很容易地调整它,让它在尝试之前等待许可,但它 运行 初始化了两次,所以你第二次会得到正确的数据(不,我不知道为什么 运行s 两次)。
我在 Flutter 应用程序中使用 https://pub.dev/packages/connectivity#-example-tab- 中的示例代码,当 运行 在 Android 模拟器上运行该应用程序时,该应用程序会看到调试 Wi-Fi 网络.但是,当我 运行 我的 Pixel 4XL 上的应用程序时,我得到的 wi-fi 名称和 BSSID 为空。
我假设我必须启用访问 Wi-Fi 设置的权限才能使用此包,但我无法在任何地方找到描述此包在 Flutter 上的要求的任何参考资料。
我使用 wi-fi 包示例中的 wi-fi 权限更新了 Android 应用程序 appmanifest 文件,但我的应用程序没有任何变化。
我创建了一个演示解决方案的示例应用程序,但显然 Stack Overflow 的人们希望我更加努力地与您分享这些信息。他们删除了我原来的答案(即使它解决了所有有问题的人的问题)。并希望我提取部分答案并在此处 post。我做了很多工作来解决这个问题并将其作为完整的应用程序示例发布,但显然这还不够。我讨厌这个。我正在努力帮助人们,但他们不喜欢对解决方案的外部引用。
我创建了一个完整的解决方案,演示了如何解决 https://github.com/johnwargo/flutter-android-connectivity-permissions 中的这个问题。
Flutter 似乎无法查询应用程序用户的权限,因此有人创建了 Flutter permissions_handler 包。将其添加到我的应用程序,以及原始问题中显示的代码变体,解决了我的问题。
我很快意识到 Flutter 存储库上的答案不完整,任何试图实施此解决方案的人都需要一些帮助。为了方便这些开发人员,我在此存储库中创建了一个完整的示例应用程序。
这是我所做的
从项目的 pubspec.yaml
文件开始,我添加了连接和 permissions_handler 包:
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
函数中添加了一些代码:
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
并且会发生其他权限检查内容的 none。甚至从未像预期的那样要求用户获得许可。
要解决此问题,请打开项目的 android/app/src/main/AndroidManifest.xml
文件并将位置权限添加到应用程序的配置中:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
我用的是course设置,我觉得你也可以用fine
很多时候,作者会告诉您要更改什么权限,但不会告诉您应该在文件中的什么位置进行更改。我没有做很多本机 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 启动应用程序时,它看起来像这样:
对于我的特定应用程序,当应用程序未 运行ning 时,我不关心从设备获取设置,因此我选择了“仅在使用该应用程序时允许”。如果您查看控制台,您将看到以下内容:
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 设置;那是因为代码的编写方式,你可以很容易地调整它,让它在尝试之前等待许可,但它 运行 初始化了两次,所以你第二次会得到正确的数据(不,我不知道为什么 运行s 两次)。