Skip to content

Commit

Permalink
Fixes #56: Can not host non-media files on Android 11 and above
Browse files Browse the repository at this point in the history
Signed-off-by: huynguyennovem <[email protected]>
  • Loading branch information
huynguyennovem committed May 7, 2023
1 parent 302eb69 commit 0c650bf
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 0 deletions.
2 changes: 2 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
<!--flutter_downloader-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />

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

<application
android:label="NetShare"
android:name="${applicationName}"
Expand Down
15 changes: 15 additions & 0 deletions lib/ui/server/server_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,21 @@ class _ServerWidgetState extends State<ServerWidget> {
return;
}

// Additional check for Android limitation (Android 11 and above,
// see: https://developer.android.com/training/data-storage/manage-all-files#all-files-access-google-play)
final needGrantPermission = await UtilityFunctions.isNeedAccessAllFileStoragePermission;
if(needGrantPermission) {
final isPermissionGranted = await UtilityFunctions.checkManageExternalStoragePermission(
onPermanentlyDenied: () => context.showOpenSettingsDialog(),
);
if (!isPermissionGranted) {
if (mounted) {
context.showSnackbar('Need storage permission to continue');
}
return;
}
}

// Router instance to handler requests.
// Use shelf_router.Router(notFoundHandler: _staticHandler(dir.path))
// as a fallback for static handler (may use this later)
Expand Down
39 changes: 39 additions & 0 deletions lib/util/utility_functions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,37 @@ class UtilityFunctions {
}
}

static Future<bool> checkManageExternalStoragePermission({
Function? onGranted,
Function? onDenied,
Function? onPermanentlyDenied,
}) async {
final status = await Permission.manageExternalStorage.status;
switch (status) {
case PermissionStatus.granted:
onGranted?.call();
return true;
case PermissionStatus.permanentlyDenied:
onPermanentlyDenied?.call();
return false;
default:
{
final requested = await Permission.manageExternalStorage.request();
switch (requested) {
case PermissionStatus.granted:
onGranted?.call();
return true;
case PermissionStatus.permanentlyDenied:
onPermanentlyDenied?.call();
return false;
default:
onDenied?.call();
return false;
}
}
}
}

static Future<int> get androidSDKVersion async {
DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
final androidInfo = await deviceInfoPlugin.androidInfo;
Expand All @@ -97,6 +128,14 @@ class UtilityFunctions {
return 28 >= sdkVersion;
}

static Future<bool> get isNeedAccessAllFileStoragePermission async {
if (!Platform.isAndroid) {
return false;
}
final sdkVersion = await androidSDKVersion;
return 30 <= sdkVersion;
}

/// Parse ip (v4) address with [rawInput] which has format:
/// ip:port (eg: 192.168.0.100:8080)
static Tuple2<String, int> parseIPAddress(String rawInput) {
Expand Down

0 comments on commit 0c650bf

Please sign in to comment.