mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
//xplat/js/react-native-github/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/permissions:permissionsAndroid (#45742)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45742 Changelog: [Internal] Reviewed By: christophpurrer Differential Revision: D60303780 fbshipit-source-id: ea5fa127762888ff81e9c452cba323399ba45ca2
This commit is contained in:
committed by
Facebook GitHub Bot
parent
7c1740a44c
commit
e99e5d8bc0
@@ -3569,7 +3569,7 @@ public class com/facebook/react/modules/network/TLSSocketFactory : javax/net/ssl
|
||||
public fun getSupportedCipherSuites ()[Ljava/lang/String;
|
||||
}
|
||||
|
||||
public class com/facebook/react/modules/permissions/PermissionsModule : com/facebook/fbreact/specs/NativePermissionsAndroidSpec, com/facebook/react/modules/core/PermissionListener {
|
||||
public final class com/facebook/react/modules/permissions/PermissionsModule : com/facebook/fbreact/specs/NativePermissionsAndroidSpec, com/facebook/react/modules/core/PermissionListener {
|
||||
public fun <init> (Lcom/facebook/react/bridge/ReactApplicationContext;)V
|
||||
public fun checkPermission (Ljava/lang/String;Lcom/facebook/react/bridge/Promise;)V
|
||||
public fun onRequestPermissionsResult (I[Ljava/lang/String;[I)Z
|
||||
|
||||
-204
@@ -1,204 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.modules.permissions;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.util.SparseArray;
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.fbreact.specs.NativePermissionsAndroidSpec;
|
||||
import com.facebook.react.bridge.Callback;
|
||||
import com.facebook.react.bridge.Promise;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.bridge.WritableNativeMap;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.facebook.react.modules.core.PermissionAwareActivity;
|
||||
import com.facebook.react.modules.core.PermissionListener;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/** Module that exposes the Android M Permission system to JS. */
|
||||
@ReactModule(name = NativePermissionsAndroidSpec.NAME)
|
||||
public class PermissionsModule extends NativePermissionsAndroidSpec implements PermissionListener {
|
||||
|
||||
private static final String ERROR_INVALID_ACTIVITY = "E_INVALID_ACTIVITY";
|
||||
private final SparseArray<Callback> mCallbacks;
|
||||
private int mRequestCode = 0;
|
||||
private final String GRANTED = "granted";
|
||||
private final String DENIED = "denied";
|
||||
private final String NEVER_ASK_AGAIN = "never_ask_again";
|
||||
|
||||
public PermissionsModule(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
mCallbacks = new SparseArray<Callback>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the app has the permission given. successCallback is called with true if the
|
||||
* permission had been granted, false otherwise. See {@link Activity#checkSelfPermission}.
|
||||
*/
|
||||
@Override
|
||||
public void checkPermission(final String permission, final Promise promise) {
|
||||
Context context = getReactApplicationContext().getBaseContext();
|
||||
promise.resolve(context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the app should display a message explaining why a certain permission is needed.
|
||||
* successCallback is called with true if the app should display a message, false otherwise. This
|
||||
* message is only displayed if the user has revoked this permission once before, and if the
|
||||
* permission dialog will be shown to the user (the user can choose to not be shown that dialog
|
||||
* again). For devices before Android M, this always returns false. See {@link
|
||||
* Activity#shouldShowRequestPermissionRationale}.
|
||||
*/
|
||||
@Override
|
||||
public void shouldShowRequestPermissionRationale(final String permission, final Promise promise) {
|
||||
try {
|
||||
promise.resolve(
|
||||
getPermissionAwareActivity().shouldShowRequestPermissionRationale(permission));
|
||||
} catch (IllegalStateException e) {
|
||||
promise.reject(ERROR_INVALID_ACTIVITY, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the given permission. successCallback is called with GRANTED if the permission had been
|
||||
* granted, DENIED or NEVER_ASK_AGAIN otherwise. For devices before Android M, this checks if the
|
||||
* user has the permission given or not and resolves with GRANTED or DENIED. See {@link
|
||||
* Activity#checkSelfPermission}.
|
||||
*/
|
||||
@Override
|
||||
public void requestPermission(final String permission, final Promise promise) {
|
||||
Context context = getReactApplicationContext().getBaseContext();
|
||||
if (context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED) {
|
||||
promise.resolve(GRANTED);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
PermissionAwareActivity activity = getPermissionAwareActivity();
|
||||
|
||||
mCallbacks.put(
|
||||
mRequestCode,
|
||||
new Callback() {
|
||||
@Override
|
||||
public void invoke(Object... args) {
|
||||
int[] results = (int[]) args[0];
|
||||
if (results.length > 0 && results[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
promise.resolve(GRANTED);
|
||||
} else {
|
||||
PermissionAwareActivity activity = (PermissionAwareActivity) args[1];
|
||||
if (activity.shouldShowRequestPermissionRationale(permission)) {
|
||||
promise.resolve(DENIED);
|
||||
} else {
|
||||
promise.resolve(NEVER_ASK_AGAIN);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
activity.requestPermissions(new String[] {permission}, mRequestCode, this);
|
||||
mRequestCode++;
|
||||
} catch (IllegalStateException e) {
|
||||
promise.reject(ERROR_INVALID_ACTIVITY, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestMultiplePermissions(final ReadableArray permissions, final Promise promise) {
|
||||
final WritableMap grantedPermissions = new WritableNativeMap();
|
||||
final ArrayList<String> permissionsToCheck = new ArrayList<String>();
|
||||
int checkedPermissionsCount = 0;
|
||||
|
||||
Context context = getReactApplicationContext().getBaseContext();
|
||||
|
||||
for (int i = 0; i < permissions.size(); i++) {
|
||||
String perm = permissions.getString(i);
|
||||
|
||||
if (context.checkSelfPermission(perm) == PackageManager.PERMISSION_GRANTED) {
|
||||
grantedPermissions.putString(perm, GRANTED);
|
||||
checkedPermissionsCount++;
|
||||
} else {
|
||||
permissionsToCheck.add(perm);
|
||||
}
|
||||
}
|
||||
if (permissions.size() == checkedPermissionsCount) {
|
||||
promise.resolve(grantedPermissions);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
|
||||
PermissionAwareActivity activity = getPermissionAwareActivity();
|
||||
|
||||
mCallbacks.put(
|
||||
mRequestCode,
|
||||
new Callback() {
|
||||
@Override
|
||||
public void invoke(Object... args) {
|
||||
int[] results = (int[]) args[0];
|
||||
PermissionAwareActivity activity = (PermissionAwareActivity) args[1];
|
||||
for (int j = 0; j < permissionsToCheck.size(); j++) {
|
||||
String permission = permissionsToCheck.get(j);
|
||||
if (results.length > 0 && results[j] == PackageManager.PERMISSION_GRANTED) {
|
||||
grantedPermissions.putString(permission, GRANTED);
|
||||
} else {
|
||||
if (activity.shouldShowRequestPermissionRationale(permission)) {
|
||||
grantedPermissions.putString(permission, DENIED);
|
||||
} else {
|
||||
grantedPermissions.putString(permission, NEVER_ASK_AGAIN);
|
||||
}
|
||||
}
|
||||
}
|
||||
promise.resolve(grantedPermissions);
|
||||
}
|
||||
});
|
||||
|
||||
activity.requestPermissions(permissionsToCheck.toArray(new String[0]), mRequestCode, this);
|
||||
mRequestCode++;
|
||||
} catch (IllegalStateException e) {
|
||||
promise.reject(ERROR_INVALID_ACTIVITY, e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Method called by the activity with the result of the permission request. */
|
||||
@Override
|
||||
public boolean onRequestPermissionsResult(
|
||||
int requestCode, String[] permissions, int[] grantResults) {
|
||||
try {
|
||||
Callback callback = mCallbacks.get(requestCode);
|
||||
if (callback != null) {
|
||||
callback.invoke(grantResults, getPermissionAwareActivity());
|
||||
mCallbacks.remove(requestCode);
|
||||
} else {
|
||||
FLog.w("PermissionsModule", "Unable to find callback with requestCode %d", requestCode);
|
||||
}
|
||||
return mCallbacks.size() == 0;
|
||||
} catch (IllegalStateException e) {
|
||||
FLog.e(
|
||||
"PermissionsModule",
|
||||
e,
|
||||
"Unexpected invocation of `onRequestPermissionsResult` with invalid current activity");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private PermissionAwareActivity getPermissionAwareActivity() {
|
||||
Activity activity = getCurrentActivity();
|
||||
if (activity == null) {
|
||||
throw new IllegalStateException(
|
||||
"Tried to use permissions API while not attached to an " + "Activity.");
|
||||
} else if (!(activity instanceof PermissionAwareActivity)) {
|
||||
throw new IllegalStateException(
|
||||
"Tried to use permissions API but the host Activity doesn't"
|
||||
+ " implement PermissionAwareActivity.");
|
||||
}
|
||||
return (PermissionAwareActivity) activity;
|
||||
}
|
||||
}
|
||||
+189
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.modules.permissions
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.pm.PackageManager
|
||||
import android.util.SparseArray
|
||||
import com.facebook.common.logging.FLog
|
||||
import com.facebook.fbreact.specs.NativePermissionsAndroidSpec
|
||||
import com.facebook.react.bridge.Callback
|
||||
import com.facebook.react.bridge.Promise
|
||||
import com.facebook.react.bridge.ReactApplicationContext
|
||||
import com.facebook.react.bridge.ReadableArray
|
||||
import com.facebook.react.bridge.WritableNativeMap
|
||||
import com.facebook.react.module.annotations.ReactModule
|
||||
import com.facebook.react.modules.core.PermissionAwareActivity
|
||||
import com.facebook.react.modules.core.PermissionListener
|
||||
import java.util.ArrayList
|
||||
|
||||
/** Module that exposes the Android M Permission system to JS. */
|
||||
@ReactModule(name = NativePermissionsAndroidSpec.NAME)
|
||||
public class PermissionsModule(reactContext: ReactApplicationContext?) :
|
||||
NativePermissionsAndroidSpec(reactContext), PermissionListener {
|
||||
|
||||
private val callbacks: SparseArray<Callback> = SparseArray<Callback>()
|
||||
private var requestCode = 0
|
||||
private val GRANTED = "granted"
|
||||
private val DENIED = "denied"
|
||||
private val NEVER_ASK_AGAIN = "never_ask_again"
|
||||
|
||||
/**
|
||||
* Check if the app has the permission given. successCallback is called with true if the
|
||||
* permission had been granted, false otherwise. See [Activity.checkSelfPermission].
|
||||
*/
|
||||
override public fun checkPermission(permission: String, promise: Promise): Unit {
|
||||
val context = getReactApplicationContext().getBaseContext()
|
||||
promise.resolve(context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the app should display a message explaining why a certain permission is needed.
|
||||
* successCallback is called with true if the app should display a message, false otherwise. This
|
||||
* message is only displayed if the user has revoked this permission once before, and if the
|
||||
* permission dialog will be shown to the user (the user can choose to not be shown that dialog
|
||||
* again). For devices before Android M, this always returns false. See
|
||||
* [permissionAwareActivity.shouldShowRequestPermissionRationale].
|
||||
*/
|
||||
override public fun shouldShowRequestPermissionRationale(
|
||||
permission: String?,
|
||||
promise: Promise
|
||||
): Unit {
|
||||
try {
|
||||
promise.resolve(permissionAwareActivity.shouldShowRequestPermissionRationale(permission))
|
||||
} catch (e: IllegalStateException) {
|
||||
promise.reject(ERROR_INVALID_ACTIVITY, e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the given permission. successCallback is called with GRANTED if the permission had been
|
||||
* granted, DENIED or NEVER_ASK_AGAIN otherwise. For devices before Android M, this checks if the
|
||||
* user has the permission given or not and resolves with GRANTED or DENIED. See
|
||||
* [Activity.checkSelfPermission].
|
||||
*/
|
||||
override public fun requestPermission(permission: String, promise: Promise): Unit {
|
||||
val context = getReactApplicationContext().getBaseContext()
|
||||
if (context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED) {
|
||||
promise.resolve(GRANTED)
|
||||
return
|
||||
}
|
||||
try {
|
||||
val activity = permissionAwareActivity
|
||||
callbacks.put(
|
||||
requestCode,
|
||||
object : Callback {
|
||||
override public operator fun invoke(vararg args: Any?) {
|
||||
val results = args[0] as IntArray
|
||||
if (results.size > 0 && results[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
promise.resolve(GRANTED)
|
||||
} else {
|
||||
val callbackActivity = args[1] as PermissionAwareActivity
|
||||
if (callbackActivity.shouldShowRequestPermissionRationale(permission)) {
|
||||
promise.resolve(DENIED)
|
||||
} else {
|
||||
promise.resolve(NEVER_ASK_AGAIN)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
activity.requestPermissions(arrayOf(permission), requestCode, this)
|
||||
requestCode++
|
||||
} catch (e: IllegalStateException) {
|
||||
promise.reject(ERROR_INVALID_ACTIVITY, e)
|
||||
}
|
||||
}
|
||||
|
||||
override public fun requestMultiplePermissions(
|
||||
permissions: ReadableArray,
|
||||
promise: Promise
|
||||
): Unit {
|
||||
val grantedPermissions = WritableNativeMap()
|
||||
val permissionsToCheck = ArrayList<String>()
|
||||
var checkedPermissionsCount = 0
|
||||
val context = getReactApplicationContext().getBaseContext()
|
||||
for (i in 0 until permissions.size()) {
|
||||
val perm = permissions.getString(i)
|
||||
if (context.checkSelfPermission(perm) == PackageManager.PERMISSION_GRANTED) {
|
||||
grantedPermissions.putString(perm, GRANTED)
|
||||
checkedPermissionsCount++
|
||||
} else {
|
||||
permissionsToCheck.add(perm)
|
||||
}
|
||||
}
|
||||
if (permissions.size() == checkedPermissionsCount) {
|
||||
promise.resolve(grantedPermissions)
|
||||
return
|
||||
}
|
||||
try {
|
||||
val activity = permissionAwareActivity
|
||||
callbacks.put(
|
||||
requestCode,
|
||||
object : Callback {
|
||||
override public operator fun invoke(vararg args: Any?) {
|
||||
val results = args[0] as IntArray
|
||||
val callbackActivity = args[1] as PermissionAwareActivity
|
||||
for (j in permissionsToCheck.indices) {
|
||||
val permission = permissionsToCheck[j]
|
||||
if (results.size > 0 && results[j] == PackageManager.PERMISSION_GRANTED) {
|
||||
grantedPermissions.putString(permission, GRANTED)
|
||||
} else {
|
||||
if (callbackActivity.shouldShowRequestPermissionRationale(permission)) {
|
||||
grantedPermissions.putString(permission, DENIED)
|
||||
} else {
|
||||
grantedPermissions.putString(permission, NEVER_ASK_AGAIN)
|
||||
}
|
||||
}
|
||||
}
|
||||
promise.resolve(grantedPermissions)
|
||||
}
|
||||
})
|
||||
activity.requestPermissions(permissionsToCheck.toTypedArray<String>(), requestCode, this)
|
||||
requestCode++
|
||||
} catch (e: IllegalStateException) {
|
||||
promise.reject(ERROR_INVALID_ACTIVITY, e)
|
||||
}
|
||||
}
|
||||
|
||||
/** Method called by the activity with the result of the permission request. */
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int,
|
||||
permissions: Array<String>,
|
||||
grantResults: IntArray
|
||||
): Boolean =
|
||||
try {
|
||||
val callback = callbacks[requestCode]
|
||||
if (callback != null) {
|
||||
callback.invoke(grantResults, permissionAwareActivity)
|
||||
callbacks.remove(requestCode)
|
||||
} else {
|
||||
FLog.w("PermissionsModule", "Unable to find callback with requestCode %d", requestCode)
|
||||
}
|
||||
callbacks.size() == 0
|
||||
} catch (e: IllegalStateException) {
|
||||
FLog.e(
|
||||
"PermissionsModule",
|
||||
e,
|
||||
"Unexpected invocation of `onRequestPermissionsResult` with invalid current activity")
|
||||
false
|
||||
}
|
||||
|
||||
private val permissionAwareActivity: PermissionAwareActivity
|
||||
get() {
|
||||
val activity = getCurrentActivity()
|
||||
checkNotNull(activity) { "Tried to use permissions API while not attached to an Activity." }
|
||||
check(activity is PermissionAwareActivity) {
|
||||
("Tried to use permissions API but the host Activity doesn't implement PermissionAwareActivity.")
|
||||
}
|
||||
return activity
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private const val ERROR_INVALID_ACTIVITY = "E_INVALID_ACTIVITY"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user