cordova-diagnostic-plugin

repository·master·Indexed 20 days ago

https://github.com/dpa99c/cordova-diagnostic-plugin

A Cordova/Phonegap plugin (version 7.3.1) providing a cross-platform API to check device diagnostic information, hardware availability, and manage runtime permissions for system features including Location, WiFi, Camera, Bluetooth, Notifications, Microphone, Contacts, and Calendar. It allows developers to programmatically request permissions, check authorization statuses, and redirect users to system settings on Android and iOS.

Tokens
29.3K
Snippets
91
Records
97
Agent score
19%

What's inside cordova-diagnostic-plugin

  1. Overview of the Cordova diagnostic plugin

    master
    The cordova-diagnostic-plugin provides a unified API to check device diagnostic information, such as hardware availability, permission statuses, and system settings (e.g., Bluetooth, WiFi, Location, Camera, etc.) across both Android and iOS platforms. It allows developers to programmatically request permissions and redirect users to system settings to enable specific features.
  2. Understand permissionStatus constants for Android and iOS

    master

    The cordova.plugins.diagnostic.permissionStatus object contains constants used to represent the state of a requested permission.

    Android States

    • NOT_REQUESTED: App has not yet requested access.
    • DENIED_ONCE: User denied access without checking "Never Ask Again". The app can request again.
    • DENIED_ALWAYS: User denied access and checked "Never Ask Again". The app cannot request again via dialog; the user must manually change settings.
    • GRANTED: User granted access (or device is Android 5.x or below).

    Note: The plugin uses HTML5 local storage to distinguish between NOT_REQUESTED and DENIED_ALWAYS on Android, as the native API returns the same value for both. Clearing local storage will reset this distinction.

    iOS States

    • NOT_REQUESTED: App has not yet requested access.
    • DENIED_ALWAYS: User denied access. Manual settings change required.
    • RESTRICTED: Permission is unavailable (e.g., due to parental controls).
    • GRANTED: Permission granted.
    • GRANTED_WHEN_IN_USE: (Location only) Permission granted for foreground use only.
    • PROVISIONAL: (Notifications only) Provisionally authorized for non-interruptive notifications.
    • EPHEMERAL: (Notifications only) Authorized for a limited time.

    Common States

    • UNKNOWN: Returned when the OS has not yet provided a concrete status (e.g., a timeout). Treat this as transient and retry.
    if(somePermissionStatus === cordova.plugins.diagnostic.permissionStatus.GRANTED){
        // Do something
    }
  3. How the plugin module structure works

    master

    The core plugin module is exposed via the global cordova.plugins.diagnostic object. This core object acts as an alias for all functions and properties provided by the optional modules you have installed.

    Warning: If you attempt to call a function belonging to an optional module that was not included in your installation (via the config.xml preference), a JavaScript error will be raised.

  4. Manage concurrent permission requests on Android

    master

    On Android, only one permission request can be active at a time. If you attempt to make a second request while one is already in progress, the plugin will trigger the error callback.

    To handle this, use isRequestingPermission() to check the current state. If a request is active, you can use registerPermissionRequestCompleteHandler() to wait for it to finish before starting your own request.

    Methods:

    • isRequestingPermission(): Returns true if a request is currently in progress.
    • registerPermissionRequestCompleteHandler(successCallback): Registers a callback for when a request completes. Pass null to de-register the handler.
    var isRequesting = cordova.plugins.diagnostic.isRequestingPermission();
    if(!isRequesting){
        requestSomePermissions();
    }else{
        cordova.plugins.diagnostic.registerPermissionRequestCompleteHandler(function(statuses){
            cordova.plugins.diagnostic.registerPermissionRequestCompleteHandler(null); // de-register handler after single call
            requestSomePermissions();
        });
    }
  5. Handle Android 11+ 'Only this time' permission behavior

    master

    On Android 11+, users can select "Only this time", which grants permission for the current session but revokes it upon app restart. Because Android's programmatic state for a revoked permission is the same as a permission never requested (NOT_REQUESTED/DENIED_ALWAYS), the plugin may incorrectly report DENIED_ALWAYS due to its internal tracking.

    Workaround: If the device is running Android 11+ (API level 30+) and the status is DENIED_ALWAYS, you should treat it as DENIED_ONCE and attempt to request it again, as the user might have simply selected the temporary option in the previous session.

    let diagnostic, deviceOS;
    let cameraDeniedAlwaysAfterRequesting = false;
    
    function onDeviceReady(){
        diagnostic = cordova.plugins.diagnostic;
        diagnostic.getDeviceOSVersion(function(osDetails){
            deviceOS = osDetails;
            checkCameraPermission();
        })
    }
    
    function checkCameraPermission(){
        diagnostic.getPermissionAuthorizationStatus(function(status){
    
            // Workaround for Android 11+ 'Only this time' option
            if(deviceOS.apiLevel >= 30 && status === diagnostic.permissionStatus.DENIED_ALWAYS && !cameraDeniedAlwaysAfterRequesting){
                status = diagnostic.permissionStatus.DENIED_ONCE;
            }
    
            switch(status){
                case diagnostic.permissionStatus.GRANTED:
                    console.log("Camera permission is allowed")
                    break;
                case diagnostic.permissionStatus.NOT_REQUESTED:
                    console.log("Camera permission not requested yet - requesting...")
                    requestCameraPermission();
                    break;
                case diagnostic.permissionStatus.DENIED_ONCE:
                    console.log("Camera permission denied but can still request - requesting...")
                    requestCameraPermission();
                    break;
                case diagnostic.permissionStatus.DENIED_ALWAYS:
                    console.log("Camera permission permanently denied - can't request");
                    break;
            }
        }, console.error, diagnostic.permission.CAMERA)
    };
    
    function requestCameraPermission(){
        diagnostic.requestRuntimePermission(function(status){
            if(status === diagnostic.permissionStatus.DENIED_ALWAYS){
                cameraDeniedAlwaysAfterRequesting = true;
            }
            checkCameraPermission();
        }, console.error, diagnostic.permission.CAMERA);
    }
    
    document.addEventListener("deviceready", onDeviceReady, false);
  6. Handle Motion/Fitness tracking permissions on iOS

    master

    The Motion module allows you to manage motion and fitness tracking permissions on iOS devices. Note that on iOS, determining the exact authorization outcome (granted vs denied) often requires using the Pedometer API indirectly.

    Key behaviors:

    • Requesting Permission: The native dialog can only be invoked once per app installation. If the user denies permission, you cannot re-invoke the dialog; you must instruct the user to change it manually in the iOS Settings app.
    • Hardware Support: Motion tracking requires an M7 co-processor or above (e.g., iPhone 5s+, iPad Air+, iPad Mini 2+). Pedometer Event Tracking (needed to determine authorization outcome) is only available on iPhones, not iPads.
    if(status === cordova.plugins.diagnostic.motionStatus.NOT_REQUESTED){
        cordova.plugins.diagnostic.requestMotionAuthorization(successCallback, errorCallback);
    }
  7. Select specific functional modules to reduce plugin size

    master

    The plugin is split into optional functional modules. To avoid installing redundant code, you can specify exactly which modules you need via a <preference> in your config.xml.

    Important: You must add the preference to config.xml before installing the plugin. If you need to change modules after installation, you must uninstall and re-install the plugin.

    1. Add preference to config.xml

    Use the cordova.plugins.diagnostic.modules preference with a space-separated list of capitalized module names.

    To include only specific modules:

    <preference name="cordova.plugins.diagnostic.modules" value="LOCATION BLUETOOTH WIFI" />

    To install only the core module (no optional modules):

    <preference name="cordova.plugins.diagnostic.modules" value="" />

    2. Re-install the plugin

    If the plugin is already installed, run:

    cordova plugin rm cordova.plugins.diagnostic --nosave && cordova plugin add cordova.plugins.diagnostic --nosave

    Supported Modules

    • LOCATION (Android & iOS)
    • BLUETOOTH (Android & iOS)
    • WIFI (Android & iOS)
    • CAMERA (Android & iOS)
    • NOTIFICATIONS (Android & iOS)
    • MICROPHONE (Android & iOS)
    • CONTACTS (Android & iOS)
    • CALENDAR (Android & iOS)
    • REMINDERS (iOS only)
    • MOTION (iOS only)
    • NFC (Android only)
    • EXTERNAL_STORAGE (Android only)
  8. Configure AndroidX library versions during installation

    master

    The plugin depends on AndroidX (Jetpack) libraries. While it pins default versions, you can override them at installation time using the ANDROIDX_VERSION (for legacy) and ANDROIDX_APPCOMPAT_VERSION variables.

    $ cordova plugin add cordova.plugins.diagnostic --variable ANDROIDX_VERSION=1.0.0 --variable ANDROIDX_APPCOMPAT_VERSION=1.3.1
  9. Configure Android Manifest permissions

    master

    Some plugin functions require specific permissions to be declared in your AndroidManifest.xml. The plugin does not add these automatically to avoid requesting unnecessary permissions.

    You can add them manually in /platforms/android/AndroidManifest.xml or use the cordova-custom-config plugin in your config.xml to manage them declaratively.

    <platform name="android">
        <plugin name="cordova-custom-config" version="*"/>
        <custom-config-file target="AndroidManifest.xml" parent="/*">
            <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
            <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
        </custom-config-file>
    </platform>
  10. Override iOS usage description messages

    master

    On iOS, when requesting permission for device functionality, the system displays a message to the user. The plugin adds default messages to your {project}-Info.plist under various NS*UsageDescription keys.

    To provide custom messages that explain why your app needs specific permissions, use <edit-config> blocks in your config.xml file within the ios platform section. Use mode="merge" to ensure your custom strings are applied to the existing keys.

    <platform name="ios">
        <edit-config file="*-Info.plist" target="NSLocationAlwaysUsageDescription" mode="merge">
            <string>My custom message for always using location.</string>
        </edit-config>
        <edit-config file="*-Info.plist" target="NSLocationWhenInUseUsageDescription" mode="merge">
            <string>My custom message for using location when in use.</string>
        </edit-config>
    </platform>
  11. Manage location accuracy authorization

    master

    On iOS 14+ and Android 12+, users can grant location access with reduced accuracy. Use these methods to manage and check that state.

    Check current accuracy: Use getLocationAccuracyAuthorization() to get the current state from locationAccuracyAuthorization constants.

    Request temporary full accuracy (iOS 14+ only): If your app has been granted reduced accuracy but needs high-accuracy GPS (e.g., for navigation), call requestTemporaryFullAccuracyAuthorization(purpose, successCallback, errorCallback).

    Requirements for iOS: You must define a purpose key in your *-Info.plist under NSLocationTemporaryUsageDescriptionDictionary.

    Example config.xml setup:

    <platform name="ios">
      <config-file target="*-Info.plist" parent="NSLocationTemporaryUsageDescriptionDictionary">
        <dict>
          <key>navigation</key>
          <string>This app requires access to your exact location in order to provide SatNav route navigation.</string>
        </dict>
      </config-file>
    </platform>
    cordova.plugins.diagnostic.requestTemporaryFullAccuracyAuthorization("navigation", function(accuracyAuthorization){
        switch(accuracyAuthorization){
            case cordova.plugins.diagnostic.locationAccuracyAuthorization.FULL:
                console.log("Full accuracy authorized");
                break;
            case cordova.plugins.diagnostic.locationAccuracyAuthorization.REDUCED:
                console.log("Full accuracy denied");
                break;
        }
    }, function(error){
        console.error(error);
    });
  12. Install the cordova-diagnostic-plugin

    master

    You can install the plugin using the Cordova, Phonegap, or Ionic CLI. By default, all functional modules are included.

    $ cordova plugin add cordova.plugins.diagnostic
    $ phonegap plugin add cordova.plugins.diagnostic
    $ ionic cordova plugin add cordova.plugins.diagnostic
    $ cordova plugin add cordova.plugins.diagnostic