From cdc8229ede7ff13bd749b377b44a78dd9a74d243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franc=CC=A7ois=20Lallemand?= Date: Tue, 26 Apr 2022 11:51:12 +0200 Subject: [PATCH] feat: Added a permission requestion for getSimCards and leave the native function bypass it if needed --- README.md | 133 +++++++++++------- .../SimCardsManagerModule.java | 2 +- ios/SimCardsManager.m | 2 +- src/index.tsx | 36 ++++- 4 files changed, 122 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index 2702bd4..84d618f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # react-native-sim-cards-manager A new library that merge multiple sim cards libraries into a single one: + - https://github.com/markneh/react-native-esim - https://github.com/pocesar/react-native-sim-data @@ -8,7 +9,6 @@ Bridges have been adapted, so you will have to adapt your code if you come from Bugs fixed and some improvements have been made. - ## Installation ```sh @@ -21,9 +21,10 @@ npm install react-native-sim-cards-manager **Minimum API Level is 22** -*TelephonyManager* require Android permission **READ_PHONE_STATE**: +_TelephonyManager_ require Android permission **READ_PHONE_STATE**: Add in your Android Manifest: + ```xml @@ -35,103 +36,141 @@ Add in your Android Manifest: **Minimum API Level is 12 for eSIM methods** -Note: At the moment *(iOS 14.2)* there might a bug in iOS SDK which returns uknown result before eSIM setup completion. More about it [here](https://developer.apple.com/forums/thread/662001) +Note: At the moment _(iOS 14.2)_ there might a bug in iOS SDK which returns uknown result before eSIM setup completion. More about it [here](https://developer.apple.com/forums/thread/662001) ## Usage ### Get sim cards The list can be empty (no simcards detected) or one/many element(s) +Two methods are availabe : + +#### Method getSimCards + +This handle the permission request and takes an optionnal _rationale_ Parameter ```ts -import { SimManager } from "react-native-sim-cards-manager"; +import { SimManager } from 'react-native-sim-cards-manager'; + +SimCardsManagerModule.getSimCards({ + title: 'App Permission', + message: 'Custom message', + buttonNeutral: 'Not now', + buttonNegative: 'Not OK', + buttonPositive: 'OK', +}) + .then((array: Array) => { + // + }) + .catch((error) => { + // + }); +``` -SimCardsManagerModule.getSimCards().then((array: Array)=>{ +#### Method getSimCardsNative + +This is the method used internally by getSimCards. It does not handle the permission request and leaves the user of this lib. + +```ts +import { SimManager } from 'react-native-sim-cards-manager'; + +SimCardsManagerModule.getSimCardsNative() + .then((array: Array) => { // -}).catch((error)=>{ + }) + .catch((error) => { // -}) + }); ``` Available set of data per platform: -| Platform | iOS | Android | -|------------------- |----- |--------- | -| carrierName | ✅ | ✅ | -| displayName | ❌ | ✅ | -| isoCountryCode | ✅ | ✅ | -| mobileCountryCode | ✅ | ✅ | -| mobileNetworkCode | ✅ | ✅ | -| isNetworkRoaming | ❌ | ✅ | -| isDataRoaming | ❌ | ✅ | -| simSlotIndex | ❌ | ✅ | -| phoneNumber | ❌ | ✅ | -| simSerialNumber | ❌ | ✅ | -| subscriptionId | ❌ | ✅ | -| allowsVOIP | ✅ | ❌ | +| Platform | iOS | Android | +| ----------------- | --- | ------- | +| carrierName | ✅ | ✅ | +| displayName | ❌ | ✅ | +| isoCountryCode | ✅ | ✅ | +| mobileCountryCode | ✅ | ✅ | +| mobileNetworkCode | ✅ | ✅ | +| isNetworkRoaming | ❌ | ✅ | +| isDataRoaming | ❌ | ✅ | +| simSlotIndex | ❌ | ✅ | +| phoneNumber | ❌ | ✅ | +| simSerialNumber | ❌ | ✅ | +| subscriptionId | ❌ | ✅ | +| allowsVOIP | ✅ | ❌ | ### Esim is supported Return true/false is the device support eSim feature ```ts -import { SimManager } from "react-native-sim-cards-manager"; +import { SimManager } from 'react-native-sim-cards-manager'; -SimCardsManagerModule.isEsimSupported().then((isSupported: boolean)=>{ +SimCardsManagerModule.isEsimSupported() + .then((isSupported: boolean) => { // -}).catch((error)=>{ + }) + .catch((error) => { // -}) + }); ``` ### Setup eSim with an activation code Entry parameters for the bridge: -| Entry parameters | Mandatory | Description | -|------------------ |----------- |----------------------------------------------------------------------------------------------------------------- | -| address | N/A | The address of the carrier network’s eSIM server | -| confirmationCode | N/A | The provisioning request’s confirmation code, provided by the network operator when initiating an eSIM download | -| iccid | N/A | The provisioning request’s eUICC identifier | -| address | N/A | The provisioning request’s Integrated Circuit Card Identifier | -| matchingId | N/A | The provisioning request’s matching identifier | -| oid | N/A | The provisioning request’s Object Identifier | +| Entry parameters | Mandatory | Description | +| ---------------- | --------- | --------------------------------------------------------------------------------------------------------------- | +| address | N/A | The address of the carrier network’s eSIM server | +| confirmationCode | N/A | The provisioning request’s confirmation code, provided by the network operator when initiating an eSIM download | +| iccid | N/A | The provisioning request’s eUICC identifier | +| address | N/A | The provisioning request’s Integrated Circuit Card Identifier | +| matchingId | N/A | The provisioning request’s matching identifier | +| oid | N/A | The provisioning request’s Object Identifier | Error code that can be returned by the bridge: -| Error code | Description | -|-------------- |----------------------------------------------------------------------------------- | -| 0 | Feature not available for that OS / device | -| 1 | The device doesn't support a cellular plan | -| 2 | The OS failed to add the new plan | -| 3 **(iOS)** | The OS has returned an unknow error | -| 3 **(Android)** | The OS has returned an error **or** something goes wrong with the Intent/Activity | +| Error code | Description | +| --------------- | --------------------------------------------------------------------------------- | +| 0 | Feature not available for that OS / device | +| 1 | The device doesn't support a cellular plan | +| 2 | The OS failed to add the new plan | +| 3 **(iOS)** | The OS has returned an unknow error | +| 3 **(Android)** | The OS has returned an error **or** something goes wrong with the Intent/Activity | + ```ts -import { SimManager } from "react-native-sim-cards-manager"; +import { SimManager } from 'react-native-sim-cards-manager'; SimCardsManagerModule.setupEsim({ - confirmationCode, address: '', -}).then((isPlanAdded: boolean)=>{ - // -}).catch((error)=>{ - // + confirmationCode, + address: '', }) + .then((isPlanAdded: boolean) => { + // + }) + .catch((error) => { + // + }); ``` - ## Changelog ### 1.0.2 + - Remove 'deviceID' on Android because it require high privilege - Adding permission management on Android (READ_PHONE_STATE) ### 1.0.1 + - Android bug fixes ### 1.0.0 + - First stable release ### 0.9.9 + - iOS implementation - Android implementation - RN implementation diff --git a/android/src/main/java/com/reactnativesimcardsmanager/SimCardsManagerModule.java b/android/src/main/java/com/reactnativesimcardsmanager/SimCardsManagerModule.java index 13fab21..ea3217f 100644 --- a/android/src/main/java/com/reactnativesimcardsmanager/SimCardsManagerModule.java +++ b/android/src/main/java/com/reactnativesimcardsmanager/SimCardsManagerModule.java @@ -56,7 +56,7 @@ public String getName() { @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP_MR1) @ReactMethod - public void getSimCards(Promise promise) { + public void getSimCardsNative(Promise promise) { WritableArray simCardsList = new WritableNativeArray(); TelephonyManager telManager = (TelephonyManager) mReactContext.getSystemService(Context.TELEPHONY_SERVICE); diff --git a/ios/SimCardsManager.m b/ios/SimCardsManager.m index 7084631..2e6c837 100644 --- a/ios/SimCardsManager.m +++ b/ios/SimCardsManager.m @@ -10,7 +10,7 @@ @implementation SimCardsManager RCT_EXPORT_MODULE() -RCT_EXPORT_METHOD(getSimCards:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { +RCT_EXPORT_METHOD(getSimCardsNative:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { NSMutableArray *simCardsList = [[NSMutableArray alloc]init]; diff --git a/src/index.tsx b/src/index.tsx index b3ed932..cd2ebd1 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,4 +1,4 @@ -import { NativeModules, Platform } from 'react-native'; +import { NativeModules, PermissionsAndroid, Platform, Rationale } from 'react-native'; const LINKING_ERROR = `The package 'react-native-sim-cards-manager' doesn't seem to be linked. Make sure: \n\n` + @@ -17,6 +17,33 @@ const SimCardsManagerModule = NativeModules.SimCardsManager } ); +export async function requestCellularNetworkPermission(then: () => any, rationale?: Rationale) { + if (Platform.OS == 'android') { + const granted = await PermissionsAndroid.request( + PermissionsAndroid.PERMISSIONS.READ_PHONE_STATE, + rationale ?? { + title: 'App Permission', + message: 'App needs access to get informations of your cellular network', + buttonNeutral: 'Ask Me Later', + buttonNegative: 'Cancel', + buttonPositive: 'OK', + } + ); + console.log(granted); + console.log(PermissionsAndroid.RESULTS); + if ( + granted === PermissionsAndroid.RESULTS.GRANTED || + granted === PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN + ) { + return then(); + } else { + return Promise.reject({ code: '3', message: 'Permission not granted' }); + } + } else { + return then(); + } +} + export type EsimConfig = { address: string; confirmationCode?: string; @@ -27,9 +54,14 @@ export type EsimConfig = { }; type SimManager = { - getSimCards(): Promise>; + getSimCards(rationale?: Rationale): Promise>; // Permission request handled by react-native-sim-cards-manager + getSimCardsNative(): Promise>; // Permission request left to be handled by the user setupEsim(config: EsimConfig): Promise; isEsimSupported(): Promise; }; +SimCardsManagerModule.getSimCards = async () => { + return await requestCellularNetworkPermission(NativeModules.SimCardsManager.getSimCardsNative); +}; + export default SimCardsManagerModule as SimManager;