mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-02-24 10:28:50 +01:00
Handle android permission request on dart side
This commit is contained in:
parent
80689fa431
commit
1cf2e565ba
5 changed files with 242 additions and 1 deletions
18
app/lib/mobile/android/permission_util.dart
Normal file
18
app/lib/mobile/android/permission_util.dart
Normal file
|
@ -0,0 +1,18 @@
|
|||
import 'package:logging/logging.dart';
|
||||
import 'package:nc_photos/stream_extension.dart';
|
||||
import 'package:nc_photos_plugin/nc_photos_plugin.dart';
|
||||
|
||||
Future<Map<String, int>> requestPermissionsForResult(
|
||||
List<String> permissions) async {
|
||||
Map<String, int>? result;
|
||||
final resultFuture = Permission.stream
|
||||
.whereType<PermissionRequestResult>()
|
||||
.first
|
||||
.then((ev) => result = ev.grantResults);
|
||||
await Permission.request(permissions);
|
||||
await resultFuture;
|
||||
_log.info("[requestPermissionsForResult] Result: $result");
|
||||
return result!;
|
||||
}
|
||||
|
||||
final _log = Logger("mobile.android.permission_util");
|
|
@ -11,7 +11,8 @@ import io.flutter.plugin.common.MethodChannel
|
|||
import io.flutter.plugin.common.PluginRegistry
|
||||
|
||||
class NcPhotosPlugin : FlutterPlugin, ActivityAware,
|
||||
PluginRegistry.ActivityResultListener {
|
||||
PluginRegistry.ActivityResultListener,
|
||||
PluginRegistry.RequestPermissionsResultListener {
|
||||
companion object {
|
||||
const val ACTION_SHOW_IMAGE_PROCESSOR_RESULT =
|
||||
K.ACTION_SHOW_IMAGE_PROCESSOR_RESULT
|
||||
|
@ -81,6 +82,19 @@ class NcPhotosPlugin : FlutterPlugin, ActivityAware,
|
|||
contentUriMethodChannel.setMethodCallHandler(
|
||||
ContentUriChannelHandler(flutterPluginBinding.applicationContext)
|
||||
)
|
||||
|
||||
permissionChannelHandler =
|
||||
PermissionChannelHandler(flutterPluginBinding.applicationContext)
|
||||
permissionChannel = EventChannel(
|
||||
flutterPluginBinding.binaryMessenger,
|
||||
PermissionChannelHandler.EVENT_CHANNEL
|
||||
)
|
||||
permissionChannel.setStreamHandler(permissionChannelHandler)
|
||||
permissionMethodChannel = MethodChannel(
|
||||
flutterPluginBinding.binaryMessenger,
|
||||
PermissionChannelHandler.METHOD_CHANNEL
|
||||
)
|
||||
permissionMethodChannel.setMethodCallHandler(permissionChannelHandler)
|
||||
}
|
||||
|
||||
override fun onDetachedFromEngine(
|
||||
|
@ -94,30 +108,39 @@ class NcPhotosPlugin : FlutterPlugin, ActivityAware,
|
|||
mediaStoreMethodChannel.setMethodCallHandler(null)
|
||||
imageProcessorMethodChannel.setMethodCallHandler(null)
|
||||
contentUriMethodChannel.setMethodCallHandler(null)
|
||||
permissionMethodChannel.setMethodCallHandler(null)
|
||||
}
|
||||
|
||||
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
|
||||
mediaStoreChannelHandler.onAttachedToActivity(binding)
|
||||
permissionChannelHandler.onAttachedToActivity(binding)
|
||||
pluginBinding = binding
|
||||
binding.addActivityResultListener(this)
|
||||
binding.addRequestPermissionsResultListener(this)
|
||||
}
|
||||
|
||||
override fun onReattachedToActivityForConfigChanges(
|
||||
binding: ActivityPluginBinding
|
||||
) {
|
||||
mediaStoreChannelHandler.onReattachedToActivityForConfigChanges(binding)
|
||||
permissionChannelHandler.onReattachedToActivityForConfigChanges(binding)
|
||||
pluginBinding = binding
|
||||
binding.addActivityResultListener(this)
|
||||
binding.addRequestPermissionsResultListener(this)
|
||||
}
|
||||
|
||||
override fun onDetachedFromActivity() {
|
||||
mediaStoreChannelHandler.onDetachedFromActivity()
|
||||
permissionChannelHandler.onDetachedFromActivity()
|
||||
pluginBinding?.removeActivityResultListener(this)
|
||||
pluginBinding?.removeRequestPermissionsResultListener(this)
|
||||
}
|
||||
|
||||
override fun onDetachedFromActivityForConfigChanges() {
|
||||
mediaStoreChannelHandler.onDetachedFromActivityForConfigChanges()
|
||||
permissionChannelHandler.onDetachedFromActivityForConfigChanges()
|
||||
pluginBinding?.removeActivityResultListener(this)
|
||||
pluginBinding?.removeRequestPermissionsResultListener(this)
|
||||
}
|
||||
|
||||
override fun onActivityResult(
|
||||
|
@ -141,6 +164,27 @@ class NcPhotosPlugin : FlutterPlugin, ActivityAware,
|
|||
}
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int, permissions: Array<String>, grantResults: IntArray
|
||||
): Boolean {
|
||||
return try {
|
||||
when (requestCode) {
|
||||
K.PERMISSION_REQUEST_CODE -> {
|
||||
permissionChannelHandler.onRequestPermissionsResult(
|
||||
requestCode, permissions, grantResults
|
||||
)
|
||||
}
|
||||
|
||||
else -> false
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
Log.e(
|
||||
TAG, "Failed while onActivityResult, requestCode=$requestCode"
|
||||
)
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private var pluginBinding: ActivityPluginBinding? = null
|
||||
|
||||
private lateinit var lockChannel: MethodChannel
|
||||
|
@ -151,7 +195,10 @@ class NcPhotosPlugin : FlutterPlugin, ActivityAware,
|
|||
private lateinit var mediaStoreMethodChannel: MethodChannel
|
||||
private lateinit var imageProcessorMethodChannel: MethodChannel
|
||||
private lateinit var contentUriMethodChannel: MethodChannel
|
||||
private lateinit var permissionChannel: EventChannel
|
||||
private lateinit var permissionMethodChannel: MethodChannel
|
||||
|
||||
private lateinit var lockChannelHandler: LockChannelHandler
|
||||
private lateinit var mediaStoreChannelHandler: MediaStoreChannelHandler
|
||||
private lateinit var permissionChannelHandler: PermissionChannelHandler
|
||||
}
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
package com.nkming.nc_photos.plugin
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityAware
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
|
||||
import io.flutter.plugin.common.EventChannel
|
||||
import io.flutter.plugin.common.MethodCall
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
import io.flutter.plugin.common.PluginRegistry
|
||||
|
||||
class PermissionChannelHandler(context: Context) :
|
||||
MethodChannel.MethodCallHandler, EventChannel.StreamHandler, ActivityAware,
|
||||
PluginRegistry.RequestPermissionsResultListener {
|
||||
companion object {
|
||||
const val EVENT_CHANNEL = "${K.LIB_ID}/permission"
|
||||
const val METHOD_CHANNEL = "${K.LIB_ID}/permission_method"
|
||||
|
||||
private const val TAG = "PermissionChannelHandler"
|
||||
}
|
||||
|
||||
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
|
||||
activity = binding.activity
|
||||
}
|
||||
|
||||
override fun onReattachedToActivityForConfigChanges(
|
||||
binding: ActivityPluginBinding
|
||||
) {
|
||||
activity = binding.activity
|
||||
}
|
||||
|
||||
override fun onDetachedFromActivity() {
|
||||
activity = null
|
||||
}
|
||||
|
||||
override fun onDetachedFromActivityForConfigChanges() {
|
||||
activity = null
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int, permissions: Array<String>, grantResults: IntArray
|
||||
): Boolean {
|
||||
return if (requestCode == K.PERMISSION_REQUEST_CODE) {
|
||||
eventSink?.success(buildMap {
|
||||
put("event", "RequestPermissionsResult")
|
||||
put(
|
||||
"grantResults",
|
||||
permissions.zip(grantResults.toTypedArray()).toMap()
|
||||
)
|
||||
})
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
override fun onListen(arguments: Any?, events: EventChannel.EventSink) {
|
||||
eventSink = events
|
||||
}
|
||||
|
||||
override fun onCancel(arguments: Any?) {
|
||||
eventSink = null
|
||||
}
|
||||
|
||||
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
|
||||
when (call.method) {
|
||||
"request" -> {
|
||||
try {
|
||||
request(call.argument("permissions")!!, result)
|
||||
} catch (e: Throwable) {
|
||||
result.error("systemException", e.toString(), null)
|
||||
}
|
||||
}
|
||||
|
||||
"hasWriteExternalStorage" -> {
|
||||
try {
|
||||
result.success(
|
||||
PermissionUtil.hasWriteExternalStorage(context)
|
||||
)
|
||||
} catch (e: Throwable) {
|
||||
result.error("systemException", e.toString(), null)
|
||||
}
|
||||
}
|
||||
|
||||
"hasReadExternalStorage" -> {
|
||||
try {
|
||||
result.success(
|
||||
PermissionUtil.hasReadExternalStorage(context)
|
||||
)
|
||||
} catch (e: Throwable) {
|
||||
result.error("systemException", e.toString(), null)
|
||||
}
|
||||
}
|
||||
|
||||
else -> result.notImplemented()
|
||||
}
|
||||
}
|
||||
|
||||
private fun request(
|
||||
permissions: List<String>, result: MethodChannel.Result
|
||||
) {
|
||||
if (activity == null) {
|
||||
result.error("systemException", "Activity is not ready", null)
|
||||
return
|
||||
}
|
||||
PermissionUtil.request(activity!!, *permissions.toTypedArray())
|
||||
result.success(null)
|
||||
}
|
||||
|
||||
private val context = context
|
||||
private var activity: Activity? = null
|
||||
private var eventSink: EventChannel.EventSink? = null
|
||||
}
|
|
@ -7,3 +7,4 @@ export 'src/lock.dart';
|
|||
export 'src/media_store.dart';
|
||||
export 'src/native_event.dart';
|
||||
export 'src/notification.dart';
|
||||
export 'src/permission.dart';
|
||||
|
|
62
plugin/lib/src/permission.dart
Normal file
62
plugin/lib/src/permission.dart
Normal file
|
@ -0,0 +1,62 @@
|
|||
// ignore_for_file: constant_identifier_names
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:nc_photos_plugin/src/k.dart' as k;
|
||||
|
||||
class Permission {
|
||||
static const READ_EXTERNAL_STORAGE =
|
||||
"android.permission.READ_EXTERNAL_STORAGE";
|
||||
static const WRITE_EXTERNAL_STORAGE =
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE";
|
||||
|
||||
static Future<void> request(List<String> permissions) =>
|
||||
_methodChannel.invokeMethod("request", <String, dynamic>{
|
||||
"permissions": permissions,
|
||||
});
|
||||
|
||||
static Future<bool> hasWriteExternalStorage() async {
|
||||
return (await _methodChannel
|
||||
.invokeMethod<bool>("hasWriteExternalStorage"))!;
|
||||
}
|
||||
|
||||
static Future<bool> hasReadExternalStorage() async {
|
||||
return (await _methodChannel.invokeMethod<bool>("hasReadExternalStorage"))!;
|
||||
}
|
||||
|
||||
static Stream get stream => _eventStream;
|
||||
|
||||
static late final _eventStream =
|
||||
_eventChannel.receiveBroadcastStream().map((event) {
|
||||
if (event is Map) {
|
||||
switch (event["event"]) {
|
||||
case _eventRequestPermissionsResult:
|
||||
return PermissionRequestResult(
|
||||
(event["grantResults"] as Map).cast<String, int>());
|
||||
|
||||
default:
|
||||
_log.shout("[_eventStream] Unknown event: ${event["event"]}");
|
||||
}
|
||||
} else {
|
||||
return event;
|
||||
}
|
||||
});
|
||||
|
||||
static const _eventChannel = EventChannel("${k.libId}/permission");
|
||||
static const _methodChannel = MethodChannel("${k.libId}/permission_method");
|
||||
|
||||
static const _eventRequestPermissionsResult = "RequestPermissionsResult";
|
||||
|
||||
static final _log = Logger("plugin.permission.Permission");
|
||||
}
|
||||
|
||||
class PermissionRequestResult {
|
||||
static const granted = 0;
|
||||
static const denied = -1;
|
||||
|
||||
const PermissionRequestResult(this.grantResults);
|
||||
|
||||
final Map<String, int> grantResults;
|
||||
}
|
Loading…
Reference in a new issue