From 90697715b03cd41f00ae6056b469fcf26d346360 Mon Sep 17 00:00:00 2001 From: bartguz Date: Tue, 9 Nov 2021 01:11:24 +0100 Subject: [PATCH 1/3] android 10+ default subscription id additional permissions slight refactor: - reduced nesting - slightly more descriptive methods - grouped by permission and data level --- src/android/com/pbakondy/Sim.java | 322 +++++++++++++++--------------- 1 file changed, 164 insertions(+), 158 deletions(-) diff --git a/src/android/com/pbakondy/Sim.java b/src/android/com/pbakondy/Sim.java index df3542f..434adf6 100644 --- a/src/android/com/pbakondy/Sim.java +++ b/src/android/com/pbakondy/Sim.java @@ -39,6 +39,7 @@ import android.annotation.SuppressLint; import android.content.Context; import android.content.pm.PackageManager; +import android.provider.Settings.Secure; import android.os.Build; import android.Manifest; @@ -46,194 +47,192 @@ import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import java.lang.reflect.Method; import java.util.List; public class Sim extends CordovaPlugin { private static final String LOG_TAG = "CordovaPluginSim"; - - private static final String GET_SIM_INFO = "getSimInfo"; private static final String HAS_READ_PERMISSION = "hasReadPermission"; private static final String REQUEST_READ_PERMISSION = "requestReadPermission"; + private final String[] permissions = { Manifest.permission.READ_PHONE_STATE + // ,Manifest.permission.READ_PHONE_NUMBERS + // ,Manifest.permission.READ_SMS + }; private CallbackContext callback; + private final int ANDROID_VERSION_Q = 29; + @SuppressLint("HardwareIds") @Override public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { - callback = callbackContext; + this.callback = callbackContext; - if (GET_SIM_INFO.equals(action)) { - Context context = this.cordova.getActivity().getApplicationContext(); + switch (action) { + case GET_SIM_INFO: + return getSimInfo(); - TelephonyManager manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + case HAS_READ_PERMISSION: + return hasReadPermission(); - // dual SIM detection with SubscriptionManager API - // requires API 22 - // requires permission READ_PHONE_STATE - JSONArray sims = null; - Integer phoneCount = null; - Integer activeSubscriptionInfoCount = null; - Integer activeSubscriptionInfoCountMax = null; + case REQUEST_READ_PERMISSION: + return requestReadPermission(); - try { - // TelephonyManager.getPhoneCount() requires API 23 - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { - phoneCount = manager.getPhoneCount(); - } + default: + return false; + } - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP_MR1) { - - if (simPermissionGranted(Manifest.permission.READ_PHONE_STATE)) { - - SubscriptionManager subscriptionManager = (SubscriptionManager) context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); - activeSubscriptionInfoCount = subscriptionManager.getActiveSubscriptionInfoCount(); - activeSubscriptionInfoCountMax = subscriptionManager.getActiveSubscriptionInfoCountMax(); - - sims = new JSONArray(); - - List subscriptionInfos = subscriptionManager.getActiveSubscriptionInfoList(); - for (SubscriptionInfo subscriptionInfo : subscriptionInfos) { - - CharSequence carrierName = subscriptionInfo.getCarrierName(); - String countryIso = subscriptionInfo.getCountryIso(); - int dataRoaming = subscriptionInfo.getDataRoaming(); // 1 is enabled ; 0 is disabled - CharSequence displayName = subscriptionInfo.getDisplayName(); - String iccId = subscriptionInfo.getIccId(); - int mcc = subscriptionInfo.getMcc(); - int mnc = subscriptionInfo.getMnc(); - String number = subscriptionInfo.getNumber(); - int simSlotIndex = subscriptionInfo.getSimSlotIndex(); - int subscriptionId = subscriptionInfo.getSubscriptionId(); - - boolean networkRoaming = subscriptionManager.isNetworkRoaming(simSlotIndex); - - String deviceId = null; - // TelephonyManager.getDeviceId(slotId) requires API 23 - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { - deviceId = manager.getDeviceId(simSlotIndex); - } - - JSONObject simData = new JSONObject(); - - simData.put("carrierName", carrierName.toString()); - simData.put("displayName", displayName.toString()); - simData.put("countryCode", countryIso); - simData.put("mcc", mcc); - simData.put("mnc", mnc); - simData.put("isNetworkRoaming", networkRoaming); - simData.put("isDataRoaming", (dataRoaming == 1)); - simData.put("simSlotIndex", simSlotIndex); - simData.put("phoneNumber", number); - if (deviceId != null) { - simData.put("deviceId", deviceId); - } - simData.put("simSerialNumber", iccId); - simData.put("subscriptionId", subscriptionId); - - sims.put(simData); - - } - } - } - } catch (JSONException e) { - e.printStackTrace(); - } catch (Exception e) { - e.printStackTrace(); - } + } - String phoneNumber = null; - String countryCode = manager.getSimCountryIso(); - String simOperator = manager.getSimOperator(); - String carrierName = manager.getSimOperatorName(); - - String deviceId = null; - String deviceSoftwareVersion = null; - String simSerialNumber = null; - String subscriberId = null; - - int callState = manager.getCallState(); - int dataActivity = manager.getDataActivity(); - int networkType = manager.getNetworkType(); - int phoneType = manager.getPhoneType(); - int simState = manager.getSimState(); - - boolean isNetworkRoaming = manager.isNetworkRoaming(); - - if (simPermissionGranted(Manifest.permission.READ_PHONE_STATE)) { - phoneNumber = manager.getLine1Number(); - deviceId = manager.getDeviceId(); - deviceSoftwareVersion = manager.getDeviceSoftwareVersion(); - simSerialNumber = manager.getSimSerialNumber(); - subscriberId = manager.getSubscriberId(); - } + private boolean getSimInfo() throws JSONException { + Context context = this.cordova.getActivity().getApplicationContext(); + TelephonyManager manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); - String mcc = ""; - String mnc = ""; + JSONObject result = new JSONObject(); - if (simOperator.length() >= 3) { - mcc = simOperator.substring(0, 3); - mnc = simOperator.substring(3); - } + setBasicSimInfo(result, manager); + trySetPhoneCount(result, manager); + trySetSimCards(result, manager, context); + trySetSensitiveInfo(result, manager, context); + this.callback.success(result); + return true; + } - JSONObject result = new JSONObject(); + private boolean hasReadPermission() { + this.callback.sendPluginResult(new PluginResult(PluginResult.Status.OK, simAllPermissionsGranted())); + return true; + } - result.put("carrierName", carrierName); - result.put("countryCode", countryCode); - result.put("mcc", mcc); - result.put("mnc", mnc); + private boolean requestReadPermission() { + requestPermission(); + return true; + } - result.put("callState", callState); - result.put("dataActivity", dataActivity); - result.put("networkType", networkType); - result.put("phoneType", phoneType); - result.put("simState", simState); + private void trySetPhoneCount(JSONObject result, TelephonyManager manager) throws JSONException { + // TelephonyManager.getPhoneCount() requires API 23 + if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) + return; - result.put("isNetworkRoaming", isNetworkRoaming); + result.put("phoneCount", manager.getPhoneCount()); + } - if (phoneCount != null) { - result.put("phoneCount", (int)phoneCount); - } - if (activeSubscriptionInfoCount != null) { - result.put("activeSubscriptionInfoCount", (int)activeSubscriptionInfoCount); - } - if (activeSubscriptionInfoCountMax != null) { - result.put("activeSubscriptionInfoCountMax", (int)activeSubscriptionInfoCountMax); - } + // anything that requires READ_PHONE_STATE, READ_PHONE_NUMBERS or other + // permissions + private void trySetSensitiveInfo(JSONObject result, TelephonyManager manager, Context context) throws JSONException { + if (!simAllPermissionsGranted()) + return; - if (simPermissionGranted(Manifest.permission.READ_PHONE_STATE)) { - result.put("phoneNumber", phoneNumber); - result.put("deviceId", deviceId); - result.put("deviceSoftwareVersion", deviceSoftwareVersion); - result.put("simSerialNumber", simSerialNumber); - result.put("subscriberId", subscriberId); - } + result.put("phoneNumber", manager.getLine1Number()); + result.put("deviceSoftwareVersion", manager.getDeviceSoftwareVersion()); + result.put("networkType", manager.getNetworkType()); - if (sims != null && sims.length() != 0) { - result.put("cards", sims); - } + if (android.os.Build.VERSION.SDK_INT >= ANDROID_VERSION_Q) { + result.put("deviceId", Secure.getString(context.getContentResolver(), Secure.ANDROID_ID)); + } else { + result.put("deviceId", manager.getDeviceId()); + } - callbackContext.success(result); + if (android.os.Build.VERSION.SDK_INT < ANDROID_VERSION_Q) { + result.put("simSerialNumber", manager.getSimSerialNumber()); + result.put("subscriberId", manager.getSubscriberId()); + } + } - return true; - } else if (HAS_READ_PERMISSION.equals(action)) { - hasReadPermission(); - return true; - } else if (REQUEST_READ_PERMISSION.equals(action)) { - requestReadPermission(); - return true; - } else { - return false; + private void setBasicSimInfo(JSONObject result, TelephonyManager manager) throws JSONException { + String simOperator = manager.getSimOperator(); + if (simOperator.length() >= 3) { + result.put("mcc", simOperator.substring(0, 3)); + result.put("mnc", simOperator.substring(3)); } + result.put("carrierName", manager.getSimOperatorName()); + result.put("countryCode", manager.getSimCountryIso()); + result.put("callState", manager.getCallState()); + result.put("dataActivity", manager.getDataActivity()); + result.put("phoneType", manager.getPhoneType()); + result.put("simState", manager.getSimState()); + result.put("isNetworkRoaming", manager.isNetworkRoaming()); } - private void hasReadPermission() { - this.callback.sendPluginResult(new PluginResult(PluginResult.Status.OK, - simPermissionGranted(Manifest.permission.READ_PHONE_STATE))); + // dual SIM detection with SubscriptionManager API + private void trySetSimCards(JSONObject result, TelephonyManager manager, Context context) { + try { + // requires API 22 + if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP_MR1) + return; + + // requires permission READ_PHONE_STATE + if (!simAllPermissionsGranted()) + return; + + JSONArray sims = new JSONArray(); + + SubscriptionManager subscriptionManager = (SubscriptionManager) context + .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); + + result.put("activeSubscriptionInfoCount", subscriptionManager.getActiveSubscriptionInfoCount()); + result.put("activeSubscriptionInfoCountMax", subscriptionManager.getActiveSubscriptionInfoCountMax()); + + List subscriptionInfos = subscriptionManager.getActiveSubscriptionInfoList(); + for (SubscriptionInfo subscriptionInfo : subscriptionInfos) { + + JSONObject simData = new JSONObject(); + + simData.put("carrierName", subscriptionInfo.getCarrierName().toString()); + simData.put("displayName", subscriptionInfo.getDisplayName().toString()); + simData.put("countryCode", subscriptionInfo.getCountryIso()); + simData.put("mcc", subscriptionInfo.getMcc()); + simData.put("mnc", subscriptionInfo.getMnc()); + simData.put("isDataRoaming", (subscriptionInfo.getDataRoaming() == 1));// 1 is enabled ; 0 is disabled + simData.put("phoneNumber", subscriptionInfo.getNumber()); + simData.put("subscriptionId", subscriptionInfo.getSubscriptionId()); + + if (android.os.Build.VERSION.SDK_INT < ANDROID_VERSION_Q) { + simData.put("simSerialNumber", subscriptionInfo.getIccId()); + } + + int simSlotIndex = subscriptionInfo.getSimSlotIndex(); + simData.put("simSlotIndex", simSlotIndex); + simData.put("isNetworkRoaming", subscriptionManager.isNetworkRoaming(simSlotIndex)); + + // TelephonyManager.getDeviceId(slotId) requires API 23 + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M + && android.os.Build.VERSION.SDK_INT < ANDROID_VERSION_Q) { + simData.put("deviceId", manager.getDeviceId(simSlotIndex)); + } + + sims.put(simData); + + } + if (sims == null || sims.length() == 0) + return; + + trySetDefaultSubscriptionId(result); + result.put("cards", sims); + + } catch (JSONException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } } - private void requestReadPermission() { - requestPermission(Manifest.permission.READ_PHONE_STATE); + private void trySetDefaultSubscriptionId(JSONObject result) throws JSONException { + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { + // android.telephony.SubscriptionManager#getDefaultDataSubscriptionId requires + // API 24 + result.put("defaultDataSubscriptionId", SubscriptionManager.getDefaultDataSubscriptionId()); + } else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP_MR1) { + // android.telephony.SubscriptionManager#getDefaultDataSubId requires API 22, + // must be accessed through reflection + try { + Method getDefaultDataSubId = SubscriptionManager.class.getDeclaredMethod("getDefaultDataSubId"); + getDefaultDataSubId.setAccessible(true); + result.put("defaultDataSubscriptionId", getDefaultDataSubId.invoke(null)); + } catch (Exception e) { + e.printStackTrace(); + } + } } private boolean simPermissionGranted(String type) { @@ -243,18 +242,25 @@ private boolean simPermissionGranted(String type) { return cordova.hasPermission(type); } - private void requestPermission(String type) { + private boolean simAllPermissionsGranted() { + for (String permission : this.permissions) + if (!simPermissionGranted(permission)) + return false; + return true; + } + + private void requestPermission() { LOG.i(LOG_TAG, "requestPermission"); - if (!simPermissionGranted(type)) { - cordova.requestPermission(this, 12345, type); + if (!simAllPermissionsGranted()) { + cordova.requestPermissions(this, 12345, this.permissions); } else { this.callback.success(); } } @Override - public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) throws JSONException - { + public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) + throws JSONException { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { this.callback.success(); } else { From ba1b412f1fa4ad86249d7e3b2a3a47749ab8cc46 Mon Sep 17 00:00:00 2001 From: bartguz Date: Wed, 24 Nov 2021 22:36:55 +0100 Subject: [PATCH 2/3] correct permissions --- src/android/com/pbakondy/Sim.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/android/com/pbakondy/Sim.java b/src/android/com/pbakondy/Sim.java index 434adf6..759e0d2 100644 --- a/src/android/com/pbakondy/Sim.java +++ b/src/android/com/pbakondy/Sim.java @@ -56,7 +56,7 @@ public class Sim extends CordovaPlugin { private static final String HAS_READ_PERMISSION = "hasReadPermission"; private static final String REQUEST_READ_PERMISSION = "requestReadPermission"; private final String[] permissions = { Manifest.permission.READ_PHONE_STATE - // ,Manifest.permission.READ_PHONE_NUMBERS + ,Manifest.permission.READ_PHONE_NUMBERS // ,Manifest.permission.READ_SMS }; From 3b92b221106c2b159e8d494056c4b0c11d7c647e Mon Sep 17 00:00:00 2001 From: bartguz Date: Wed, 16 Feb 2022 15:38:42 +0100 Subject: [PATCH 3/3] Add or update the Azure App Service build and deployment workflow config --- .github/workflows/master_tost.yml | 56 +++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 .github/workflows/master_tost.yml diff --git a/.github/workflows/master_tost.yml b/.github/workflows/master_tost.yml new file mode 100644 index 0000000..c15e678 --- /dev/null +++ b/.github/workflows/master_tost.yml @@ -0,0 +1,56 @@ +# Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy +# More GitHub Actions for Azure: https://github.com/Azure/actions + +name: Build and deploy Node.js app to Azure Web App - tost + +on: + push: + branches: + - master + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Set up Node.js version + uses: actions/setup-node@v1 + with: + node-version: '16.x' + + - name: npm install, build, and test + run: | + npm install + npm run build --if-present + npm run test --if-present + + - name: Upload artifact for deployment job + uses: actions/upload-artifact@v2 + with: + name: node-app + path: . + + deploy: + runs-on: ubuntu-latest + needs: build + environment: + name: 'Production' + url: ${{ steps.deploy-to-webapp.outputs.webapp-url }} + + steps: + - name: Download artifact from build job + uses: actions/download-artifact@v2 + with: + name: node-app + + - name: 'Deploy to Azure Web App' + id: deploy-to-webapp + uses: azure/webapps-deploy@v2 + with: + app-name: 'tost' + slot-name: 'Production' + publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_D5ECC0B353164CB8B5D20364911AF26D }} + package: .