Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
permission_handler
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
songyanzhi
permission_handler
Commits
681bc4ca
Unverified
Commit
681bc4ca
authored
Apr 22, 2021
by
Maurits van Beusekom
Committed by
GitHub
Apr 22, 2021
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #526 from Baseflow/scoped_storage_permission
Added MANAGE_EXTERNAL_STORAGE permission
parents
14368466
70e32f8f
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
235 additions
and
208 deletions
+235
-208
permission_handler/CHANGELOG.md
+7
-0
permission_handler/android/build.gradle
+1
-1
permission_handler/android/src/main/java/com/baseflow/permissionhandler/MethodCallHandlerImpl.java
+0
-21
permission_handler/android/src/main/java/com/baseflow/permissionhandler/PermissionConstants.java
+5
-2
permission_handler/android/src/main/java/com/baseflow/permissionhandler/PermissionHandlerPlugin.java
+40
-16
permission_handler/android/src/main/java/com/baseflow/permissionhandler/PermissionManager.java
+156
-161
permission_handler/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java
+17
-3
permission_handler/example/android/app/build.gradle
+1
-1
permission_handler/example/android/app/src/main/AndroidManifest.xml
+3
-0
permission_handler/example/lib/plugin_example/permission_list.dart
+2
-1
permission_handler/ios/Classes/PermissionHandlerEnums.h
+1
-0
permission_handler/pubspec.yaml
+2
-2
No files found.
permission_handler/CHANGELOG.md
View file @
681bc4ca
## 7.0.0
This release contains the following
**breaking changes**
:
*
Updated compile SDK version to 30 in the build.gradle for handling the MANAGE_EXTERNAL_STORAGE permission;
*
Added the MANAGE_EXTERNAL_STORAGE permission for Android R and up;
*
Registered listeners on the plugin level to prevent memory leaks or unwanted behaviour.
## 6.1.3
*
Implement equality operator on the
`Permission`
class;
...
...
permission_handler/android/build.gradle
View file @
681bc4ca
...
...
@@ -28,7 +28,7 @@ project.getTasks().withType(JavaCompile){
apply
plugin:
'com.android.library'
android
{
compileSdkVersion
29
compileSdkVersion
30
defaultConfig
{
minSdkVersion
16
...
...
permission_handler/android/src/main/java/com/baseflow/permissionhandler/MethodCallHandlerImpl.java
View file @
681bc4ca
...
...
@@ -6,12 +6,9 @@ import android.content.Context;
import
androidx.annotation.NonNull
;
import
androidx.annotation.Nullable
;
import
io.flutter.plugin.common.BinaryMessenger
;
import
io.flutter.plugin.common.MethodCall
;
import
io.flutter.plugin.common.MethodChannel
;
import
io.flutter.plugin.common.MethodChannel.Result
;
import
com.baseflow.permissionhandler.PermissionManager.ActivityRegistry
;
import
com.baseflow.permissionhandler.PermissionManager.PermissionRegistry
;
import
java.util.List
;
...
...
@@ -35,26 +32,10 @@ final class MethodCallHandlerImpl implements MethodChannel.MethodCallHandler {
@Nullable
private
Activity
activity
;
@Nullable
private
ActivityRegistry
activityRegistry
;
@Nullable
private
PermissionRegistry
permissionRegistry
;
public
void
setActivity
(
@Nullable
Activity
activity
)
{
this
.
activity
=
activity
;
}
public
void
setActivityRegistry
(
@Nullable
ActivityRegistry
activityRegistry
)
{
this
.
activityRegistry
=
activityRegistry
;
}
public
void
setPermissionRegistry
(
@Nullable
PermissionRegistry
permissionRegistry
)
{
this
.
permissionRegistry
=
permissionRegistry
;
}
@Override
public
void
onMethodCall
(
@NonNull
MethodCall
call
,
@NonNull
final
Result
result
)
{
...
...
@@ -91,8 +72,6 @@ final class MethodCallHandlerImpl implements MethodChannel.MethodCallHandler {
permissionManager
.
requestPermissions
(
permissions
,
activity
,
activityRegistry
,
permissionRegistry
,
result:
:
success
,
(
String
errorCode
,
String
errorDescription
)
->
result
.
error
(
errorCode
,
...
...
permission_handler/android/src/main/java/com/baseflow/permissionhandler/PermissionConstants.java
View file @
681bc4ca
...
...
@@ -8,7 +8,8 @@ import java.lang.annotation.RetentionPolicy;
final
class
PermissionConstants
{
static
final
String
LOG_TAG
=
"permissions_handler"
;
static
final
int
PERMISSION_CODE
=
24
;
static
final
int
PERMISSION_CODE_IGNORE_BATTERY_OPTIMIZATIONS
=
5672353
;
static
final
int
PERMISSION_CODE_IGNORE_BATTERY_OPTIMIZATIONS
=
209
;
static
final
int
PERMISSION_CODE_MANAGE_EXTERNAL_STORAGE
=
210
;
//PERMISSION_GROUP
static
final
int
PERMISSION_GROUP_CALENDAR
=
0
;
...
...
@@ -33,6 +34,7 @@ final class PermissionConstants {
static
final
int
PERMISSION_GROUP_ACTIVITY_RECOGNITION
=
19
;
static
final
int
PERMISSION_GROUP_UNKNOWN
=
20
;
static
final
int
PERMISSION_GROUP_BLUETOOTH
=
21
;
static
final
int
PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE
=
22
;
@Retention
(
RetentionPolicy
.
SOURCE
)
@IntDef
({
...
...
@@ -57,6 +59,7 @@ final class PermissionConstants {
PERMISSION_GROUP_ACTIVITY_RECOGNITION
,
PERMISSION_GROUP_UNKNOWN
,
PERMISSION_GROUP_BLUETOOTH
,
PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE
})
@interface
PermissionGroup
{
}
...
...
@@ -74,7 +77,7 @@ final class PermissionConstants {
PERMISSION_STATUS_GRANTED
,
PERMISSION_STATUS_RESTRICTED
,
PERMISSION_STATUS_LIMITED
,
PERMISSION_STATUS_NEVER_ASK_AGAIN
,
PERMISSION_STATUS_NEVER_ASK_AGAIN
})
@interface
PermissionStatus
{
}
...
...
permission_handler/android/src/main/java/com/baseflow/permissionhandler/PermissionHandlerPlugin.java
View file @
681bc4ca
...
...
@@ -4,8 +4,6 @@ import android.app.Activity;
import
android.content.Context
;
import
androidx.annotation.NonNull
;
import
androidx.annotation.Nullable
;
import
com.baseflow.permissionhandler.PermissionManager.ActivityRegistry
;
import
com.baseflow.permissionhandler.PermissionManager.PermissionRegistry
;
import
io.flutter.embedding.engine.plugins.FlutterPlugin
;
import
io.flutter.embedding.engine.plugins.activity.ActivityAware
;
import
io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
;
...
...
@@ -23,11 +21,21 @@ import io.flutter.plugin.common.MethodChannel;
*/
public
final
class
PermissionHandlerPlugin
implements
FlutterPlugin
,
ActivityAware
{
private
final
PermissionManager
permissionManager
;
private
MethodChannel
methodChannel
;
@SuppressWarnings
(
"deprecation"
)
@Nullable
private
io
.
flutter
.
plugin
.
common
.
PluginRegistry
.
Registrar
pluginRegistrar
;
@Nullable
private
ActivityPluginBinding
pluginBinding
;
@Nullable
private
MethodCallHandlerImpl
methodCallHandler
;
public
PermissionHandlerPlugin
()
{
this
.
permissionManager
=
new
PermissionManager
();
}
/**
* Registers a plugin implementation that uses the stable {@code io.flutter.plugin.common}
* package.
...
...
@@ -38,13 +46,15 @@ public final class PermissionHandlerPlugin implements FlutterPlugin, ActivityAwa
@SuppressWarnings
(
"deprecation"
)
public
static
void
registerWith
(
io
.
flutter
.
plugin
.
common
.
PluginRegistry
.
Registrar
registrar
)
{
final
PermissionHandlerPlugin
plugin
=
new
PermissionHandlerPlugin
();
plugin
.
pluginRegistrar
=
registrar
;
plugin
.
registerListeners
();
plugin
.
startListening
(
registrar
.
context
(),
registrar
.
messenger
());
if
(
registrar
.
activeContext
()
instanceof
Activity
)
{
plugin
.
startListeningToActivity
(
registrar
.
activity
(),
registrar:
:
addActivityResultListener
,
registrar:
:
addRequestPermissionsResultListener
registrar
.
activity
()
);
}
}
...
...
@@ -65,10 +75,11 @@ public final class PermissionHandlerPlugin implements FlutterPlugin, ActivityAwa
@Override
public
void
onAttachedToActivity
(
@NonNull
ActivityPluginBinding
binding
)
{
startListeningToActivity
(
binding
.
getActivity
(),
binding:
:
addActivityResultListener
,
binding:
:
addRequestPermissionsResultListener
binding
.
getActivity
()
);
this
.
pluginBinding
=
binding
;
registerListeners
();
}
@Override
...
...
@@ -79,6 +90,8 @@ public final class PermissionHandlerPlugin implements FlutterPlugin, ActivityAwa
@Override
public
void
onDetachedFromActivity
()
{
stopListeningToActivity
();
deregisterListeners
();
}
@Override
...
...
@@ -95,7 +108,7 @@ public final class PermissionHandlerPlugin implements FlutterPlugin, ActivityAwa
methodCallHandler
=
new
MethodCallHandlerImpl
(
applicationContext
,
new
AppSettingsManager
(),
new
PermissionManager
()
,
this
.
permissionManager
,
new
ServiceManager
()
);
...
...
@@ -109,22 +122,33 @@ public final class PermissionHandlerPlugin implements FlutterPlugin, ActivityAwa
}
private
void
startListeningToActivity
(
Activity
activity
,
ActivityRegistry
activityRegistry
,
PermissionRegistry
permissionRegistry
Activity
activity
)
{
if
(
methodCallHandler
!=
null
)
{
methodCallHandler
.
setActivity
(
activity
);
methodCallHandler
.
setActivityRegistry
(
activityRegistry
);
methodCallHandler
.
setPermissionRegistry
(
permissionRegistry
);
}
}
private
void
stopListeningToActivity
()
{
if
(
methodCallHandler
!=
null
)
{
methodCallHandler
.
setActivity
(
null
);
methodCallHandler
.
setActivityRegistry
(
null
);
methodCallHandler
.
setPermissionRegistry
(
null
);
}
}
private
void
registerListeners
()
{
if
(
this
.
pluginRegistrar
!=
null
)
{
this
.
pluginRegistrar
.
addActivityResultListener
(
this
.
permissionManager
);
this
.
pluginRegistrar
.
addRequestPermissionsResultListener
(
this
.
permissionManager
);
}
else
if
(
pluginBinding
!=
null
)
{
this
.
pluginBinding
.
addActivityResultListener
(
this
.
permissionManager
);
this
.
pluginBinding
.
addRequestPermissionsResultListener
(
this
.
permissionManager
);
}
}
private
void
deregisterListeners
()
{
if
(
this
.
pluginBinding
!=
null
)
{
this
.
pluginBinding
.
removeActivityResultListener
(
this
.
permissionManager
);
this
.
pluginBinding
.
removeRequestPermissionsResultListener
(
this
.
permissionManager
);
}
}
}
permission_handler/android/src/main/java/com/baseflow/permissionhandler/PermissionManager.java
View file @
681bc4ca
...
...
@@ -6,12 +6,12 @@ import android.content.Intent;
import
android.content.pm.PackageManager
;
import
android.net.Uri
;
import
android.os.Build
;
import
android.os.Environment
;
import
android.os.PowerManager
;
import
android.provider.Settings
;
import
android.util.Log
;
import
androidx.annotation.Nullable
;
import
androidx.annotation.VisibleForTesting
;
import
androidx.core.app.ActivityCompat
;
import
androidx.core.app.NotificationManagerCompat
;
import
androidx.core.content.ContextCompat
;
...
...
@@ -23,15 +23,115 @@ import java.util.Map;
import
io.flutter.plugin.common.PluginRegistry
;
final
class
PermissionManager
{
@FunctionalInterface
interface
ActivityRegistry
{
void
addListener
(
PluginRegistry
.
ActivityResultListener
handler
);
final
class
PermissionManager
implements
PluginRegistry
.
ActivityResultListener
,
PluginRegistry
.
RequestPermissionsResultListener
{
@Nullable
private
ErrorCallback
errorCallback
;
@Nullable
private
RequestPermissionsSuccessCallback
successCallback
;
@Nullable
private
Activity
activity
;
private
Map
<
Integer
,
Integer
>
requestResults
;
@Override
public
boolean
onActivityResult
(
int
requestCode
,
int
resultCode
,
Intent
data
)
{
if
(
requestCode
!=
PermissionConstants
.
PERMISSION_CODE_IGNORE_BATTERY_OPTIMIZATIONS
&&
requestCode
!=
PermissionConstants
.
PERMISSION_CODE_MANAGE_EXTERNAL_STORAGE
)
{
return
false
;
}
int
status
=
resultCode
==
Activity
.
RESULT_OK
?
PermissionConstants
.
PERMISSION_STATUS_GRANTED
:
PermissionConstants
.
PERMISSION_STATUS_DENIED
;
int
permission
;
if
(
requestCode
==
PermissionConstants
.
PERMISSION_CODE_IGNORE_BATTERY_OPTIMIZATIONS
)
{
permission
=
PermissionConstants
.
PERMISSION_GROUP_IGNORE_BATTERY_OPTIMIZATIONS
;
}
else
if
(
requestCode
==
PermissionConstants
.
PERMISSION_CODE_MANAGE_EXTERNAL_STORAGE
)
{
status
=
Environment
.
isExternalStorageManager
()
?
PermissionConstants
.
PERMISSION_STATUS_GRANTED
:
PermissionConstants
.
PERMISSION_STATUS_DENIED
;
permission
=
PermissionConstants
.
PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE
;
}
else
{
return
false
;
}
HashMap
<
Integer
,
Integer
>
results
=
new
HashMap
<>();
results
.
put
(
permission
,
status
);
successCallback
.
onSuccess
(
results
);
return
true
;
}
@FunctionalInterface
interface
PermissionRegistry
{
void
addListener
(
PluginRegistry
.
RequestPermissionsResultListener
handler
);
@Override
public
boolean
onRequestPermissionsResult
(
int
requestCode
,
String
[]
permissions
,
int
[]
grantResults
)
{
if
(
requestCode
!=
PermissionConstants
.
PERMISSION_CODE
)
{
ongoing
=
false
;
return
false
;
}
for
(
int
i
=
0
;
i
<
permissions
.
length
;
i
++)
{
final
String
permissionName
=
permissions
[
i
];
@PermissionConstants
.
PermissionGroup
final
int
permission
=
PermissionUtils
.
parseManifestName
(
permissionName
);
if
(
permission
==
PermissionConstants
.
PERMISSION_GROUP_UNKNOWN
)
continue
;
final
int
result
=
grantResults
[
i
];
if
(
permission
==
PermissionConstants
.
PERMISSION_GROUP_MICROPHONE
)
{
if
(!
requestResults
.
containsKey
(
PermissionConstants
.
PERMISSION_GROUP_MICROPHONE
))
{
requestResults
.
put
(
PermissionConstants
.
PERMISSION_GROUP_MICROPHONE
,
PermissionUtils
.
toPermissionStatus
(
this
.
activity
,
permissionName
,
result
));
}
if
(!
requestResults
.
containsKey
(
PermissionConstants
.
PERMISSION_GROUP_SPEECH
))
{
requestResults
.
put
(
PermissionConstants
.
PERMISSION_GROUP_SPEECH
,
PermissionUtils
.
toPermissionStatus
(
this
.
activity
,
permissionName
,
result
));
}
}
else
if
(
permission
==
PermissionConstants
.
PERMISSION_GROUP_LOCATION_ALWAYS
)
{
@PermissionConstants
.
PermissionStatus
int
permissionStatus
=
PermissionUtils
.
toPermissionStatus
(
this
.
activity
,
permissionName
,
result
);
if
(!
requestResults
.
containsKey
(
PermissionConstants
.
PERMISSION_GROUP_LOCATION_ALWAYS
))
{
requestResults
.
put
(
PermissionConstants
.
PERMISSION_GROUP_LOCATION_ALWAYS
,
permissionStatus
);
}
}
else
if
(
permission
==
PermissionConstants
.
PERMISSION_GROUP_LOCATION
)
{
@PermissionConstants
.
PermissionStatus
int
permissionStatus
=
PermissionUtils
.
toPermissionStatus
(
this
.
activity
,
permissionName
,
result
);
if
(
Build
.
VERSION
.
SDK_INT
<
Build
.
VERSION_CODES
.
Q
)
{
if
(!
requestResults
.
containsKey
(
PermissionConstants
.
PERMISSION_GROUP_LOCATION_ALWAYS
))
{
requestResults
.
put
(
PermissionConstants
.
PERMISSION_GROUP_LOCATION_ALWAYS
,
permissionStatus
);
}
}
if
(!
requestResults
.
containsKey
(
PermissionConstants
.
PERMISSION_GROUP_LOCATION_WHEN_IN_USE
))
{
requestResults
.
put
(
PermissionConstants
.
PERMISSION_GROUP_LOCATION_WHEN_IN_USE
,
permissionStatus
);
}
requestResults
.
put
(
permission
,
permissionStatus
);
}
else
if
(!
requestResults
.
containsKey
(
permission
))
{
requestResults
.
put
(
permission
,
PermissionUtils
.
toPermissionStatus
(
this
.
activity
,
permissionName
,
result
));
}
PermissionUtils
.
updatePermissionShouldShowStatus
(
this
.
activity
,
permission
);
}
this
.
successCallback
.
onSuccess
(
requestResults
);
ongoing
=
false
;
return
true
;
}
@FunctionalInterface
...
...
@@ -67,8 +167,6 @@ final class PermissionManager {
void
requestPermissions
(
List
<
Integer
>
permissions
,
Activity
activity
,
ActivityRegistry
activityRegistry
,
PermissionRegistry
permissionRegistry
,
RequestPermissionsSuccessCallback
successCallback
,
ErrorCallback
errorCallback
)
{
if
(
ongoing
)
{
...
...
@@ -87,7 +185,11 @@ final class PermissionManager {
return
;
}
Map
<
Integer
,
Integer
>
requestResults
=
new
HashMap
<>();
this
.
errorCallback
=
errorCallback
;
this
.
successCallback
=
successCallback
;
this
.
activity
=
activity
;
this
.
requestResults
=
new
HashMap
<>();
ArrayList
<
String
>
permissionsToRequest
=
new
ArrayList
<>();
for
(
Integer
permission
:
permissions
)
{
@PermissionConstants
.
PermissionStatus
final
int
permissionStatus
=
determinePermissionStatus
(
permission
,
activity
,
activity
);
...
...
@@ -111,21 +213,26 @@ final class PermissionManager {
}
else
{
requestResults
.
put
(
permission
,
PermissionConstants
.
PERMISSION_STATUS_DENIED
);
}
// On Android below R, the android.permission.MANAGE_EXTERNAL_STORAGE flag in AndroidManifest.xml
// may be ignored and not visible to the App as it's a new permission setting as a whole.
if
(
permission
==
PermissionConstants
.
PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE
&&
Build
.
VERSION
.
SDK_INT
<
Build
.
VERSION_CODES
.
R
)
{
requestResults
.
put
(
permission
,
PermissionConstants
.
PERMISSION_STATUS_RESTRICTED
);
}
else
{
requestResults
.
put
(
permission
,
PermissionConstants
.
PERMISSION_STATUS_DENIED
);
}
}
continue
;
}
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
M
&&
permission
==
PermissionConstants
.
PERMISSION_GROUP_IGNORE_BATTERY_OPTIMIZATIONS
)
{
activityRegistry
.
addListener
(
new
ActivityResultListener
(
successCallback
)
);
String
packageName
=
activity
.
getPackageName
();
Intent
intent
=
new
Intent
();
intent
.
setAction
(
Settings
.
ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
);
intent
.
setData
(
Uri
.
parse
(
"package:"
+
packageName
));
activity
.
startActivityForResult
(
intent
,
PermissionConstants
.
PERMISSION_CODE_IGNORE_BATTERY_OPTIMIZATIONS
);
executeIntent
(
Settings
.
ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
,
PermissionConstants
.
PERMISSION_CODE_IGNORE_BATTERY_OPTIMIZATIONS
);
}
else
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
R
&&
permission
==
PermissionConstants
.
PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE
)
{
executeIntent
(
Settings
.
ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION
,
PermissionConstants
.
PERMISSION_CODE_MANAGE_EXTERNAL_STORAGE
);
}
else
{
permissionsToRequest
.
addAll
(
names
);
}
...
...
@@ -133,16 +240,6 @@ final class PermissionManager {
final
String
[]
requestPermissions
=
permissionsToRequest
.
toArray
(
new
String
[
0
]);
if
(
permissionsToRequest
.
size
()
>
0
)
{
permissionRegistry
.
addListener
(
new
RequestPermissionsListener
(
activity
,
requestResults
,
(
Map
<
Integer
,
Integer
>
results
)
->
{
ongoing
=
false
;
successCallback
.
onSuccess
(
results
);
})
);
ongoing
=
true
;
ActivityCompat
.
requestPermissions
(
...
...
@@ -166,7 +263,7 @@ final class PermissionManager {
if
(
permission
==
PermissionConstants
.
PERMISSION_GROUP_NOTIFICATION
)
{
return
checkNotificationPermissionStatus
(
context
);
}
if
(
permission
==
PermissionConstants
.
PERMISSION_GROUP_BLUETOOTH
)
{
if
(
permission
==
PermissionConstants
.
PERMISSION_GROUP_BLUETOOTH
)
{
return
checkBluetoothPermissionStatus
(
context
);
}
...
...
@@ -190,6 +287,14 @@ final class PermissionManager {
}
}
// On Android below R, the android.permission.MANAGE_EXTERNAL_STORAGE flag in AndroidManifest.xml
// may be ignored and not visible to the App as it's a new permission setting as a whole.
if
(
permission
==
PermissionConstants
.
PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE
)
{
if
(
Build
.
VERSION
.
SDK_INT
<
Build
.
VERSION_CODES
.
R
)
{
return
PermissionConstants
.
PERMISSION_STATUS_RESTRICTED
;
}
}
return
PermissionConstants
.
PERMISSION_STATUS_DENIED
;
}
...
...
@@ -212,6 +317,17 @@ final class PermissionManager {
return
PermissionConstants
.
PERMISSION_STATUS_RESTRICTED
;
}
}
if
(
permission
==
PermissionConstants
.
PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE
)
{
if
(
Build
.
VERSION
.
SDK_INT
<
Build
.
VERSION_CODES
.
R
)
{
return
PermissionConstants
.
PERMISSION_STATUS_RESTRICTED
;
}
return
Environment
.
isExternalStorageManager
()
?
PermissionConstants
.
PERMISSION_STATUS_GRANTED
:
PermissionConstants
.
PERMISSION_STATUS_DENIED
;
}
final
int
permissionStatus
=
ContextCompat
.
checkSelfPermission
(
context
,
name
);
if
(
permissionStatus
!=
PackageManager
.
PERMISSION_GRANTED
)
{
return
PermissionConstants
.
PERMISSION_STATUS_DENIED
;
...
...
@@ -221,6 +337,14 @@ final class PermissionManager {
return
PermissionConstants
.
PERMISSION_STATUS_GRANTED
;
}
private
void
executeIntent
(
String
action
,
int
requestCode
)
{
String
packageName
=
activity
.
getPackageName
();
Intent
intent
=
new
Intent
();
intent
.
setAction
(
action
);
intent
.
setData
(
Uri
.
parse
(
"package:"
+
packageName
));
activity
.
startActivityForResult
(
intent
,
requestCode
);
}
void
shouldShowRequestPermissionRationale
(
int
permission
,
Activity
activity
,
...
...
@@ -265,139 +389,10 @@ final class PermissionManager {
private
int
checkBluetoothPermissionStatus
(
Context
context
)
{
List
<
String
>
names
=
PermissionUtils
.
getManifestNames
(
context
,
PermissionConstants
.
PERMISSION_GROUP_BLUETOOTH
);
boolean
missingInManifest
=
names
==
null
||
names
.
isEmpty
();
if
(
missingInManifest
)
{
if
(
missingInManifest
)
{
Log
.
d
(
PermissionConstants
.
LOG_TAG
,
"Bluetooth permission missing in manifest"
);
return
PermissionConstants
.
PERMISSION_STATUS_DENIED
;
}
return
PermissionConstants
.
PERMISSION_STATUS_GRANTED
;
}
@VisibleForTesting
static
final
class
ActivityResultListener
implements
PluginRegistry
.
ActivityResultListener
{
// There's no way to unregister permission listeners in the v1 embedding, so we'll be called
// duplicate times in cases where the user denies and then grants a permission. Keep track of if
// we've responded before and bail out of handling the callback manually if this is a repeat
// call.
boolean
alreadyCalled
=
false
;
final
RequestPermissionsSuccessCallback
callback
;
@VisibleForTesting
ActivityResultListener
(
RequestPermissionsSuccessCallback
callback
)
{
this
.
callback
=
callback
;
}
@Override
public
boolean
onActivityResult
(
int
requestCode
,
int
resultCode
,
Intent
data
)
{
if
(
alreadyCalled
||
requestCode
!=
PermissionConstants
.
PERMISSION_CODE_IGNORE_BATTERY_OPTIMIZATIONS
)
{
return
false
;
}
alreadyCalled
=
true
;
final
int
status
=
resultCode
==
Activity
.
RESULT_OK
?
PermissionConstants
.
PERMISSION_STATUS_GRANTED
:
PermissionConstants
.
PERMISSION_STATUS_DENIED
;
HashMap
<
Integer
,
Integer
>
results
=
new
HashMap
<>();
results
.
put
(
PermissionConstants
.
PERMISSION_GROUP_IGNORE_BATTERY_OPTIMIZATIONS
,
status
);
callback
.
onSuccess
(
results
);
return
true
;
}
}
@VisibleForTesting
static
final
class
RequestPermissionsListener
implements
PluginRegistry
.
RequestPermissionsResultListener
{
// There's no way to unregister permission listeners in the v1 embedding, so we'll be called
// duplicate times in cases where the user denies and then grants a permission. Keep track of if
// we've responded before and bail out of handling the callback manually if this is a repeat
// call.
boolean
alreadyCalled
=
false
;
final
Activity
activity
;
final
RequestPermissionsSuccessCallback
callback
;
final
Map
<
Integer
,
Integer
>
requestResults
;
@VisibleForTesting
RequestPermissionsListener
(
Activity
activity
,
Map
<
Integer
,
Integer
>
requestResults
,
RequestPermissionsSuccessCallback
callback
)
{
this
.
activity
=
activity
;
this
.
callback
=
callback
;
this
.
requestResults
=
requestResults
;
}
@Override
public
boolean
onRequestPermissionsResult
(
int
id
,
String
[]
permissions
,
int
[]
grantResults
)
{
if
(
alreadyCalled
||
id
!=
PermissionConstants
.
PERMISSION_CODE
)
{
return
false
;
}
alreadyCalled
=
true
;
for
(
int
i
=
0
;
i
<
permissions
.
length
;
i
++)
{
final
String
permissionName
=
permissions
[
i
];
@PermissionConstants
.
PermissionGroup
final
int
permission
=
PermissionUtils
.
parseManifestName
(
permissionName
);
if
(
permission
==
PermissionConstants
.
PERMISSION_GROUP_UNKNOWN
)
continue
;
final
int
result
=
grantResults
[
i
];
if
(
permission
==
PermissionConstants
.
PERMISSION_GROUP_MICROPHONE
)
{
if
(!
requestResults
.
containsKey
(
PermissionConstants
.
PERMISSION_GROUP_MICROPHONE
))
{
requestResults
.
put
(
PermissionConstants
.
PERMISSION_GROUP_MICROPHONE
,
PermissionUtils
.
toPermissionStatus
(
this
.
activity
,
permissionName
,
result
));
}
if
(!
requestResults
.
containsKey
(
PermissionConstants
.
PERMISSION_GROUP_SPEECH
))
{
requestResults
.
put
(
PermissionConstants
.
PERMISSION_GROUP_SPEECH
,
PermissionUtils
.
toPermissionStatus
(
this
.
activity
,
permissionName
,
result
));
}
}
else
if
(
permission
==
PermissionConstants
.
PERMISSION_GROUP_LOCATION_ALWAYS
)
{
@PermissionConstants
.
PermissionStatus
int
permissionStatus
=
PermissionUtils
.
toPermissionStatus
(
this
.
activity
,
permissionName
,
result
);
if
(!
requestResults
.
containsKey
(
PermissionConstants
.
PERMISSION_GROUP_LOCATION_ALWAYS
))
{
requestResults
.
put
(
PermissionConstants
.
PERMISSION_GROUP_LOCATION_ALWAYS
,
permissionStatus
);
}
}
else
if
(
permission
==
PermissionConstants
.
PERMISSION_GROUP_LOCATION
)
{
@PermissionConstants
.
PermissionStatus
int
permissionStatus
=
PermissionUtils
.
toPermissionStatus
(
this
.
activity
,
permissionName
,
result
);
if
(
Build
.
VERSION
.
SDK_INT
<
Build
.
VERSION_CODES
.
Q
)
{
if
(!
requestResults
.
containsKey
(
PermissionConstants
.
PERMISSION_GROUP_LOCATION_ALWAYS
))
{
requestResults
.
put
(
PermissionConstants
.
PERMISSION_GROUP_LOCATION_ALWAYS
,
permissionStatus
);
}
}
if
(!
requestResults
.
containsKey
(
PermissionConstants
.
PERMISSION_GROUP_LOCATION_WHEN_IN_USE
))
{
requestResults
.
put
(
PermissionConstants
.
PERMISSION_GROUP_LOCATION_WHEN_IN_USE
,
permissionStatus
);
}
requestResults
.
put
(
permission
,
permissionStatus
);
}
else
if
(!
requestResults
.
containsKey
(
permission
))
{
requestResults
.
put
(
permission
,
PermissionUtils
.
toPermissionStatus
(
this
.
activity
,
permissionName
,
result
));
}
PermissionUtils
.
updatePermissionShouldShowStatus
(
this
.
activity
,
permission
);
}
this
.
callback
.
onSuccess
(
requestResults
);
return
true
;
}
}
}
permission_handler/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java
View file @
681bc4ca
...
...
@@ -6,6 +6,7 @@ import android.content.Context;
import
android.content.pm.PackageInfo
;
import
android.content.pm.PackageManager
;
import
android.os.Build
;
import
android.os.Environment
;
import
android.util.Log
;
import
androidx.annotation.RequiresApi
;
...
...
@@ -60,6 +61,8 @@ public class PermissionUtils {
return
PermissionConstants
.
PERMISSION_GROUP_ACCESS_MEDIA_LOCATION
;
case
Manifest
.
permission
.
ACTIVITY_RECOGNITION
:
return
PermissionConstants
.
PERMISSION_GROUP_ACTIVITY_RECOGNITION
;
case
Manifest
.
permission
.
MANAGE_EXTERNAL_STORAGE
:
return
PermissionConstants
.
PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE
;
default
:
return
PermissionConstants
.
PERMISSION_GROUP_UNKNOWN
;
}
...
...
@@ -177,8 +180,11 @@ public class PermissionUtils {
if
(
hasPermissionInManifest
(
context
,
permissionNames
,
Manifest
.
permission
.
READ_EXTERNAL_STORAGE
))
permissionNames
.
add
(
Manifest
.
permission
.
READ_EXTERNAL_STORAGE
);
if
(
hasPermissionInManifest
(
context
,
permissionNames
,
Manifest
.
permission
.
WRITE_EXTERNAL_STORAGE
))
permissionNames
.
add
(
Manifest
.
permission
.
WRITE_EXTERNAL_STORAGE
);
if
(
Build
.
VERSION
.
SDK_INT
<
Build
.
VERSION_CODES
.
Q
||
(
Build
.
VERSION
.
SDK_INT
==
Build
.
VERSION_CODES
.
Q
&&
Environment
.
isExternalStorageLegacy
()))
{
if
(
hasPermissionInManifest
(
context
,
permissionNames
,
Manifest
.
permission
.
WRITE_EXTERNAL_STORAGE
))
permissionNames
.
add
(
Manifest
.
permission
.
WRITE_EXTERNAL_STORAGE
);
break
;
}
break
;
case
PermissionConstants
.
PERMISSION_GROUP_IGNORE_BATTERY_OPTIMIZATIONS
:
...
...
@@ -197,7 +203,7 @@ public class PermissionUtils {
break
;
case
PermissionConstants
.
PERMISSION_GROUP_ACTIVITY_RECOGNITION
:
// The AC
CESS_MEDIA_LOCA
TION permission is introduced in Android Q, meaning we should
// The AC
TIVITY_RECOGNI
TION permission is introduced in Android Q, meaning we should
// not handle permissions on pre Android Q devices.
if
(
Build
.
VERSION
.
SDK_INT
<
Build
.
VERSION_CODES
.
Q
)
return
null
;
...
...
@@ -210,6 +216,14 @@ public class PermissionUtils {
if
(
hasPermissionInManifest
(
context
,
permissionNames
,
Manifest
.
permission
.
BLUETOOTH
))
permissionNames
.
add
(
Manifest
.
permission
.
BLUETOOTH
);
break
;
case
PermissionConstants
.
PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE
:
// The MANAGE_EXTERNAL_STORAGE permission is introduced in Android R, meaning we should
// not handle permissions on pre Android R devices.
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
R
&&
hasPermissionInManifest
(
context
,
permissionNames
,
Manifest
.
permission
.
MANAGE_EXTERNAL_STORAGE
))
permissionNames
.
add
(
Manifest
.
permission
.
MANAGE_EXTERNAL_STORAGE
);
break
;
case
PermissionConstants
.
PERMISSION_GROUP_NOTIFICATION
:
case
PermissionConstants
.
PERMISSION_GROUP_MEDIA_LIBRARY
:
case
PermissionConstants
.
PERMISSION_GROUP_PHOTOS
:
...
...
permission_handler/example/android/app/build.gradle
View file @
681bc4ca
...
...
@@ -25,7 +25,7 @@ apply plugin: 'com.android.application'
apply
from:
"$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android
{
compileSdkVersion
29
compileSdkVersion
30
lintOptions
{
disable
'InvalidPackage'
...
...
permission_handler/example/android/app/src/main/AndroidManifest.xml
View file @
681bc4ca
...
...
@@ -63,6 +63,9 @@
<!-- Permissions options for the `bluetooth` group -->
<uses-permission
android:name=
"android.permission.BLUETOOTH"
/>
<!-- Permissions options for the `manage external storage` group -->
<uses-permission
android:name=
"android.permission.MANAGE_EXTERNAL_STORAGE"
/>
<application
android:name=
"io.flutter.app.FlutterApplication"
android:icon=
"@mipmap/ic_launcher"
...
...
permission_handler/example/lib/plugin_example/permission_list.dart
View file @
681bc4ca
...
...
@@ -20,7 +20,8 @@ class PermissionList extends StatelessWidget {
permission
!=
Permission
.
storage
&&
permission
!=
Permission
.
ignoreBatteryOptimizations
&&
permission
!=
Permission
.
accessMediaLocation
&&
permission
!=
Permission
.
activityRecognition
;
permission
!=
Permission
.
activityRecognition
&&
permission
!=
Permission
.
manageExternalStorage
;
}
else
{
return
permission
!=
Permission
.
unknown
&&
permission
!=
Permission
.
mediaLibrary
&&
...
...
permission_handler/ios/Classes/PermissionHandlerEnums.h
View file @
681bc4ca
...
...
@@ -118,6 +118,7 @@ typedef NS_ENUM(int, PermissionGroup) {
PermissionGroupActivityRecognition
,
PermissionGroupUnknown
,
PermissionGroupBluetooth
,
PermissionGroupManageExternalStorage
};
typedef
NS_ENUM
(
int
,
PermissionStatus
)
{
...
...
permission_handler/pubspec.yaml
View file @
681bc4ca
name
:
permission_handler
description
:
Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions.
version
:
6.1.3
version
:
7.0.0
homepage
:
https://github.com/baseflowit/flutter-permission-handler
flutter
:
...
...
@@ -16,7 +16,7 @@ dependencies:
flutter
:
sdk
:
flutter
meta
:
^1.3.0
permission_handler_platform_interface
:
^3.
1.3
permission_handler_platform_interface
:
^3.
2.0
dev_dependencies
:
flutter_test
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment