Skip to content

Commit

Permalink
4.0.0 - iOS 17 and Android 14 support (#808)
Browse files Browse the repository at this point in the history
  • Loading branch information
zoontek authored Dec 5, 2023
1 parent 63b695a commit 7f9e774
Show file tree
Hide file tree
Showing 82 changed files with 2,632 additions and 3,052 deletions.
22 changes: 14 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,9 @@ prepare_react_native_project!
# ⬇️ uncomment wanted permissions
setup_permissions([
# 'AppTrackingTransparency',
# 'BluetoothPeripheral',
# 'Bluetooth',
# 'Calendars',
# 'CalendarsWriteOnly',
# 'Camera',
# 'Contacts',
# 'FaceID',
Expand Down Expand Up @@ -108,7 +109,9 @@ setup_permissions([
<string>YOUR TEXT</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSCalendarsUsageDescription</key>
<key>NSCalendarsFullAccessUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSCalendarsWriteOnlyAccessUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSCameraUsageDescription</key>
<string>YOUR TEXT</string>
Expand All @@ -133,7 +136,7 @@ setup_permissions([
<string>YOUR TEXT</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSRemindersUsageDescription</key>
<key>NSRemindersFullAccessUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>YOUR TEXT</string>
Expand Down Expand Up @@ -183,6 +186,7 @@ Add all wanted permissions to your app `android/app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_SMS" />
Expand Down Expand Up @@ -475,6 +479,7 @@ PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE;
PERMISSIONS.ANDROID.READ_MEDIA_AUDIO;
PERMISSIONS.ANDROID.READ_MEDIA_IMAGES;
PERMISSIONS.ANDROID.READ_MEDIA_VIDEO;
PERMISSIONS.ANDROID.READ_MEDIA_VISUAL_USER_SELECTED;
PERMISSIONS.ANDROID.READ_PHONE_NUMBERS;
PERMISSIONS.ANDROID.READ_PHONE_STATE;
PERMISSIONS.ANDROID.READ_SMS;
Expand All @@ -500,8 +505,9 @@ PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE;
import {PERMISSIONS} from 'react-native-permissions';

PERMISSIONS.IOS.APP_TRACKING_TRANSPARENCY;
PERMISSIONS.IOS.BLUETOOTH_PERIPHERAL;
PERMISSIONS.IOS.BLUETOOTH;
PERMISSIONS.IOS.CALENDARS;
PERMISSIONS.IOS.CALENDARS_WRITE_ONLY;
PERMISSIONS.IOS.CAMERA;
PERMISSIONS.IOS.CONTACTS;
PERMISSIONS.IOS.FACE_ID;
Expand Down Expand Up @@ -905,18 +911,18 @@ openSettings().catch(() => console.warn('cannot open settings'));

---

#### openLimitedPhotoLibraryPicker (iOS 14+)
#### openPhotoPicker (iOS 14+)

Open a picker to update the photo selection when `PhotoLibrary` permission is `limited`. This will reject if unsupported or if full permission is already `granted`.

```ts
function openLimitedPhotoLibraryPicker(): Promise<void>;
function openPhotoPicker(): Promise<void>;
```

```js
import {openLimitedPhotoLibraryPicker} from 'react-native-permissions';
import {openPhotoPicker} from 'react-native-permissions';

openLimitedPhotoLibraryPicker().catch(() => {
openPhotoPicker().catch(() => {
console.warn('Cannot open photo library picker');
});
```
Expand Down
3 changes: 1 addition & 2 deletions RNPermissions.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,15 @@ Pod::Spec.new do |s|
s.author = package["author"]
s.homepage = package["homepage"]

s.platforms = { :ios => "12.4", :tvos => "12.4" }
s.requires_arc = true

s.source = { :git => package["repository"]["url"], :tag => s.version }
s.source_files = "ios/*.{h,m,mm}"

if ENV['RCT_NEW_ARCH_ENABLED'] == "1" then
install_modules_dependencies(s)
s.platforms = { :ios => "12.4", :tvos => "12.4" }
else
s.dependency "React-Core"
s.platforms = { :ios => "10.0", :tvos => "11.0" }
end
end
136 changes: 20 additions & 116 deletions android/src/main/java/com/zoontek/rnpermissions/RNPermissionsModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import android.provider.Settings;
import android.util.SparseArray;

import androidx.annotation.Nullable;
import androidx.annotation.NonNull;
import androidx.core.app.NotificationManagerCompat;

import com.facebook.common.logging.FLog;
Expand Down Expand Up @@ -54,96 +54,10 @@ public String getName() {
return NAME;
}

private @Nullable String getFieldName(final String permission) {
if (permission.equals("android.permission.ACCEPT_HANDOVER"))
return "ACCEPT_HANDOVER";
if (permission.equals("android.permission.ACCESS_BACKGROUND_LOCATION"))
return "ACCESS_BACKGROUND_LOCATION";
if (permission.equals("android.permission.ACCESS_COARSE_LOCATION"))
return "ACCESS_COARSE_LOCATION";
if (permission.equals("android.permission.ACCESS_FINE_LOCATION"))
return "ACCESS_FINE_LOCATION";
if (permission.equals("android.permission.ACCESS_MEDIA_LOCATION"))
return "ACCESS_MEDIA_LOCATION";
if (permission.equals("android.permission.ACTIVITY_RECOGNITION"))
return "ACTIVITY_RECOGNITION";
if (permission.equals("com.android.voicemail.permission.ADD_VOICEMAIL"))
return "ADD_VOICEMAIL";
if (permission.equals("android.permission.ANSWER_PHONE_CALLS"))
return "ANSWER_PHONE_CALLS";
if (permission.equals("android.permission.BLUETOOTH_ADVERTISE"))
return "BLUETOOTH_ADVERTISE";
if (permission.equals("android.permission.BLUETOOTH_CONNECT"))
return "BLUETOOTH_CONNECT";
if (permission.equals("android.permission.BLUETOOTH_SCAN"))
return "BLUETOOTH_SCAN";
if (permission.equals("android.permission.BODY_SENSORS"))
return "BODY_SENSORS";
if (permission.equals("android.permission.BODY_SENSORS_BACKGROUND"))
return "BODY_SENSORS_BACKGROUND";
if (permission.equals("android.permission.CALL_PHONE"))
return "CALL_PHONE";
if (permission.equals("android.permission.CAMERA"))
return "CAMERA";
if (permission.equals("android.permission.GET_ACCOUNTS"))
return "GET_ACCOUNTS";
if (permission.equals("android.permission.NEARBY_WIFI_DEVICES"))
return "NEARBY_WIFI_DEVICES";
if (permission.equals("android.permission.POST_NOTIFICATIONS"))
return "POST_NOTIFICATIONS";
if (permission.equals("android.permission.PROCESS_OUTGOING_CALLS"))
return "PROCESS_OUTGOING_CALLS";
if (permission.equals("android.permission.READ_CALENDAR"))
return "READ_CALENDAR";
if (permission.equals("android.permission.READ_CALL_LOG"))
return "READ_CALL_LOG";
if (permission.equals("android.permission.READ_CONTACTS"))
return "READ_CONTACTS";
if (permission.equals("android.permission.READ_EXTERNAL_STORAGE"))
return "READ_EXTERNAL_STORAGE";
if (permission.equals("android.permission.READ_MEDIA_AUDIO"))
return "READ_MEDIA_AUDIO";
if (permission.equals("android.permission.READ_MEDIA_IMAGES"))
return "READ_MEDIA_IMAGES";
if (permission.equals("android.permission.READ_MEDIA_VIDEO"))
return "READ_MEDIA_VIDEO";
if (permission.equals("android.permission.READ_PHONE_NUMBERS"))
return "READ_PHONE_NUMBERS";
if (permission.equals("android.permission.READ_PHONE_STATE"))
return "READ_PHONE_STATE";
if (permission.equals("android.permission.READ_SMS"))
return "READ_SMS";
if (permission.equals("android.permission.RECEIVE_MMS"))
return "RECEIVE_MMS";
if (permission.equals("android.permission.RECEIVE_SMS"))
return "RECEIVE_SMS";
if (permission.equals("android.permission.RECEIVE_WAP_PUSH"))
return "RECEIVE_WAP_PUSH";
if (permission.equals("android.permission.RECORD_AUDIO"))
return "RECORD_AUDIO";
if (permission.equals("android.permission.SEND_SMS"))
return "SEND_SMS";
if (permission.equals("android.permission.USE_SIP"))
return "USE_SIP";
if (permission.equals("android.permission.UWB_RANGING"))
return "UWB_RANGING";
if (permission.equals("android.permission.WRITE_CALENDAR"))
return "WRITE_CALENDAR";
if (permission.equals("android.permission.WRITE_CALL_LOG"))
return "WRITE_CALL_LOG";
if (permission.equals("android.permission.WRITE_CONTACTS"))
return "WRITE_CONTACTS";
if (permission.equals("android.permission.WRITE_EXTERNAL_STORAGE"))
return "WRITE_EXTERNAL_STORAGE";

return null;
}

private boolean isPermissionUnavailable(final String permission) {
String fieldName = getFieldName(permission);

if (fieldName == null)
return true;
private boolean isPermissionUnavailable(@NonNull final String permission) {
String fieldName = permission
.replace("android.permission.", "")
.replace("com.android.voicemail.permission.", "");

try {
Manifest.permission.class.getField(fieldName);
Expand Down Expand Up @@ -186,7 +100,7 @@ public void openSettings(final Promise promise) {
}

@ReactMethod
public void checkPermission(final String permission, final Promise promise) {
public void check(final String permission, final Promise promise) {
if (permission == null || isPermissionUnavailable(permission)) {
promise.resolve(UNAVAILABLE);
return;
Expand All @@ -197,8 +111,8 @@ public void checkPermission(final String permission, final Promise promise) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
promise.resolve(context.checkPermission(permission, Process.myPid(), Process.myUid())
== PackageManager.PERMISSION_GRANTED
? GRANTED
: BLOCKED);
? GRANTED
: BLOCKED);
return;
}

Expand All @@ -210,7 +124,7 @@ public void checkPermission(final String permission, final Promise promise) {
}

@ReactMethod
public void shouldShowRequestPermissionRationale(final String permission, final Promise promise) {
public void shouldShowRequestRationale(final String permission, final Promise promise) {
if (permission == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
promise.resolve(false);
return;
Expand All @@ -225,7 +139,7 @@ public void shouldShowRequestPermissionRationale(final String permission, final
}

@ReactMethod
public void requestPermission(final String permission, final Promise promise) {
public void request(final String permission, final Promise promise) {
if (permission == null || isPermissionUnavailable(permission)) {
promise.resolve(UNAVAILABLE);
return;
Expand Down Expand Up @@ -278,7 +192,7 @@ public void invoke(Object... args) {
}

@ReactMethod
public void checkMultiplePermissions(final ReadableArray permissions, final Promise promise) {
public void checkMultiple(final ReadableArray permissions, final Promise promise) {
final WritableMap output = new WritableNativeMap();
Context context = getReactApplicationContext().getBaseContext();

Expand All @@ -305,7 +219,7 @@ public void checkMultiplePermissions(final ReadableArray permissions, final Prom
}

@ReactMethod
public void requestMultiplePermissions(final ReadableArray permissions, final Promise promise) {
public void requestMultiple(final ReadableArray permissions, final Promise promise) {
final WritableMap output = new WritableNativeMap();
final ArrayList<String> permissionsToCheck = new ArrayList<String>();
int checkedPermissionsCount = 0;
Expand Down Expand Up @@ -380,21 +294,11 @@ protected Map<String, Object> getTypedExportedConstants() {
return new HashMap<>();
}

@Override
public void check(String permission, Promise promise) {
promise.reject("Permissions:check", "check is not supported on Android");
}

@Override
public void checkLocationAccuracy(Promise promise) {
promise.reject("Permissions:checkLocationAccuracy", "checkLocationAccuracy is not supported on Android");
}

@Override
public void request(String permission, Promise promise) {
promise.reject("Permissions:request", "request is not supported on Android");
}

@Override
public void requestLocationAccuracy(String purposeKey, Promise promise) {
promise.reject("Permissions:requestLocationAccuracy", "requestLocationAccuracy is not supported on Android");
Expand All @@ -406,8 +310,8 @@ public void requestNotifications(ReadableArray options, Promise promise) {
}

@Override
public void openLimitedPhotoLibraryPicker(Promise promise) {
promise.reject("Permissions:openLimitedPhotoLibraryPicker", "openLimitedPhotoLibraryPicker is not supported on Android");
public void openPhotoPicker(Promise promise) {
promise.reject("Permissions:openPhotoPicker", "openPhotoPicker is not supported on Android");
}

@Override
Expand All @@ -418,15 +322,15 @@ public boolean onRequestPermissionsResult(int requestCode, String[] permissions,
return mCallbacks.size() == 0;
} catch (IllegalStateException e) {
FLog.e(
"PermissionsModule",
e,
"Unexpected invocation of `onRequestPermissionsResult` with invalid current activity");
"PermissionsModule",
e,
"Unexpected invocation of `onRequestPermissionsResult` with invalid current activity");
return false;
} catch (NullPointerException e) {
FLog.e(
"PermissionsModule",
e,
"Unexpected invocation of `onRequestPermissionsResult` with invalid request code");
"PermissionsModule",
e,
"Unexpected invocation of `onRequestPermissionsResult` with invalid request code");
return false;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.zoontek.rnpermissions;

import androidx.annotation.NonNull;

import com.facebook.react.TurboReactPackage;
import com.facebook.react.ViewManagerOnDemandReactPackage;
import com.facebook.react.bridge.ModuleSpec;
Expand Down Expand Up @@ -39,20 +41,15 @@ protected List<ModuleSpec> getViewManagers(ReactApplicationContext reactContext)

/** {@inheritDoc} */
@Override
public @Nullable
ViewManager createViewManager(
ReactApplicationContext reactContext, String viewManagerName) {
public @Nullable ViewManager createViewManager(ReactApplicationContext reactContext, String viewManagerName) {
return null;
}

@Override
public NativeModule getModule(String name, @Nonnull ReactApplicationContext reactContext) {
switch (name) {
case RNPermissionsModule.NAME:
return new RNPermissionsModule(reactContext);
default:
return null;
}
return name.equals(RNPermissionsModule.NAME)
? new RNPermissionsModule(reactContext)
: null;
}

@Override
Expand Down Expand Up @@ -97,11 +94,13 @@ public Map<String, ReactModuleInfo> getReactModuleInfos() {
}
}

@NonNull
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
return Collections.<NativeModule>singletonList(new RNPermissionsModule(reactContext));
}

@NonNull
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
Expand Down
Loading

0 comments on commit 7f9e774

Please sign in to comment.