MOBILE-4501 diagnostic: Include diagnostic plugin
Note: The code from android & ios folders is extracted from https://github.com/dpa99c/cordova-diagnostic-plugin Co-Authored-By: Dave Alden <dpa99c@gmail.com>main
parent
0c7e7c9209
commit
df0ae16d54
|
@ -80,18 +80,9 @@
|
||||||
</platform>
|
</platform>
|
||||||
<platform name="ios">
|
<platform name="ios">
|
||||||
<resource-file src="GoogleService-Info.plist" />
|
<resource-file src="GoogleService-Info.plist" />
|
||||||
<edit-config file="*-Info.plist" mode="merge" target="NSLocationWhenInUseUsageDescription">
|
|
||||||
<string>We need your location so you can attach it as part of your submissions.</string>
|
|
||||||
</edit-config>
|
|
||||||
<edit-config file="*-Info.plist" mode="merge" target="NSLocationAlwaysUsageDescription">
|
|
||||||
<string>We need your location so you can attach it as part of your submissions.</string>
|
|
||||||
</edit-config>
|
|
||||||
<edit-config file="*-Info.plist" mode="merge" target="NSCameraUsageDescription">
|
<edit-config file="*-Info.plist" mode="merge" target="NSCameraUsageDescription">
|
||||||
<string>We need camera access to take pictures so you can attach them as part of your submissions.</string>
|
<string>We need camera access to take pictures so you can attach them as part of your submissions.</string>
|
||||||
</edit-config>
|
</edit-config>
|
||||||
<edit-config file="*-Info.plist" mode="merge" target="NSMicrophoneUsageDescription">
|
|
||||||
<string>We need microphone access to record sounds so you can attach them as part of your submissions.</string>
|
|
||||||
</edit-config>
|
|
||||||
<edit-config file="*-Info.plist" mode="merge" target="NSPhotoLibraryUsageDescription">
|
<edit-config file="*-Info.plist" mode="merge" target="NSPhotoLibraryUsageDescription">
|
||||||
<string>We need photo library access to get pictures from there so you can attach them as part of your submissions.</string>
|
<string>We need photo library access to get pictures from there so you can attach them as part of your submissions.</string>
|
||||||
</edit-config>
|
</edit-config>
|
||||||
|
|
|
@ -27,5 +27,64 @@
|
||||||
|
|
||||||
<header-file src="src/ios/SecureStorage.h" />
|
<header-file src="src/ios/SecureStorage.h" />
|
||||||
<source-file src="src/ios/SecureStorage.m" />
|
<source-file src="src/ios/SecureStorage.m" />
|
||||||
|
|
||||||
|
<config-file target="config.xml" parent="/*">
|
||||||
|
<feature name="Diagnostic">
|
||||||
|
<param name="ios-package" value="Diagnostic" />
|
||||||
|
<param name="onload" value="true" />
|
||||||
|
</feature>
|
||||||
|
</config-file>
|
||||||
|
|
||||||
|
<js-module src="www/ios/diagnostic.js" name="Diagnostic">
|
||||||
|
<merges target="com.moodle.moodlemobile.diagnostic" />
|
||||||
|
</js-module>
|
||||||
|
|
||||||
|
<header-file src="src/ios/Diagnostic.h" />
|
||||||
|
<source-file src="src/ios/Diagnostic.m" />
|
||||||
|
|
||||||
|
<!--BEGIN_MODULE LOCATION-->
|
||||||
|
<config-file target="config.xml" parent="/*">
|
||||||
|
<feature name="Diagnostic_Location">
|
||||||
|
<param name="ios-package" value="Diagnostic_Location" />
|
||||||
|
<param name="onload" value="true" />
|
||||||
|
</feature>
|
||||||
|
</config-file>
|
||||||
|
|
||||||
|
<header-file src="src/ios/Diagnostic_Location.h" />
|
||||||
|
<source-file src="src/ios/Diagnostic_Location.m" />
|
||||||
|
|
||||||
|
<framework src="CoreLocation.framework" />
|
||||||
|
|
||||||
|
<config-file target="*-Info.plist" parent="NSLocationWhenInUseUsageDescription" comment="Default usage descriptions: override as necessary in .plist">
|
||||||
|
<string>We need your location so you can attach it as part of your submissions.</string>
|
||||||
|
</config-file>
|
||||||
|
|
||||||
|
<config-file target="*-Info.plist" parent="NSLocationAlwaysUsageDescription" comment="iOS 10">
|
||||||
|
<string>We need your location so you can attach it as part of your submissions.</string>
|
||||||
|
</config-file>
|
||||||
|
<!--END_MODULE LOCATION-->
|
||||||
|
|
||||||
|
<!--BEGIN_MODULE MICROPHONE-->
|
||||||
|
<config-file target="config.xml" parent="/*">
|
||||||
|
<feature name="Diagnostic_Microphone">
|
||||||
|
<param name="ios-package" value="Diagnostic_Microphone" />
|
||||||
|
<param name="onload" value="true" />
|
||||||
|
</feature>
|
||||||
|
</config-file>
|
||||||
|
|
||||||
|
<js-module src="www/ios/diagnostic.js" name="Diagnostic_Microphone">
|
||||||
|
<merges target="com.moodle.moodlemobile.microphone" />
|
||||||
|
</js-module>
|
||||||
|
|
||||||
|
<framework src="AVFoundation.framework" />
|
||||||
|
|
||||||
|
<config-file target="*-Info.plist" parent="NSMicrophoneUsageDescription">
|
||||||
|
<string>We need microphone access to record sounds so you can attach them as part of your submissions.</string>
|
||||||
|
</config-file>
|
||||||
|
|
||||||
|
<header-file src="src/ios/Diagnostic_Microphone.h" />
|
||||||
|
<source-file src="src/ios/Diagnostic_Microphone.m" />
|
||||||
|
<!--END_MODULE MICROPHONE-->
|
||||||
|
|
||||||
</platform>
|
</platform>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,318 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package com.moodle.moodlemobile;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Imports
|
||||||
|
*/
|
||||||
|
import org.apache.cordova.CordovaWebView;
|
||||||
|
import org.apache.cordova.CallbackContext;
|
||||||
|
import org.apache.cordova.CordovaPlugin;
|
||||||
|
import org.apache.cordova.CordovaInterface;
|
||||||
|
import org.apache.cordova.PluginResult;
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.location.LocationManager;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.provider.Settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Diagnostic plugin implementation for Android
|
||||||
|
*/
|
||||||
|
public class Diagnostic_Location extends CordovaPlugin{
|
||||||
|
|
||||||
|
|
||||||
|
/*************
|
||||||
|
* Constants *
|
||||||
|
*************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tag for debug log messages
|
||||||
|
*/
|
||||||
|
public static final String TAG = "Diagnostic_Location";
|
||||||
|
|
||||||
|
private static String gpsLocationPermission = "ACCESS_FINE_LOCATION";
|
||||||
|
private static String networkLocationPermission = "ACCESS_COARSE_LOCATION";
|
||||||
|
private static String backgroundLocationPermission = "ACCESS_BACKGROUND_LOCATION";
|
||||||
|
|
||||||
|
|
||||||
|
private static final String LOCATION_MODE_HIGH_ACCURACY = "high_accuracy";
|
||||||
|
private static final String LOCATION_MODE_DEVICE_ONLY = "device_only";
|
||||||
|
private static final String LOCATION_MODE_BATTERY_SAVING = "battery_saving";
|
||||||
|
private static final String LOCATION_MODE_OFF = "location_off";
|
||||||
|
private static final String LOCATION_MODE_UNKNOWN = "unknown";
|
||||||
|
|
||||||
|
/*************
|
||||||
|
* Variables *
|
||||||
|
*************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton class instance
|
||||||
|
*/
|
||||||
|
public static Diagnostic_Location instance = null;
|
||||||
|
|
||||||
|
private Diagnostic diagnostic;
|
||||||
|
|
||||||
|
public static LocationManager locationManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current Cordova callback context (on this thread)
|
||||||
|
*/
|
||||||
|
protected CallbackContext currentContext;
|
||||||
|
|
||||||
|
private String currentLocationMode = null;
|
||||||
|
|
||||||
|
/*************
|
||||||
|
* Public API
|
||||||
|
************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*/
|
||||||
|
public Diagnostic_Location() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the context of the Command. This can then be used to do things like
|
||||||
|
* get file paths associated with the Activity.
|
||||||
|
*
|
||||||
|
* @param cordova The context of the main Activity.
|
||||||
|
* @param webView The CordovaWebView Cordova is running in.
|
||||||
|
*/
|
||||||
|
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
|
||||||
|
Log.d(TAG, "initialize()");
|
||||||
|
instance = this;
|
||||||
|
diagnostic = Diagnostic.getInstance();
|
||||||
|
|
||||||
|
try {
|
||||||
|
diagnostic.applicationContext.registerReceiver(locationProviderChangedReceiver, new IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION));
|
||||||
|
locationManager = (LocationManager) this.cordova.getActivity().getSystemService(Context.LOCATION_SERVICE);
|
||||||
|
}catch(Exception e){
|
||||||
|
diagnostic.logWarning("Unable to register Location Provider Change receiver: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
currentLocationMode = getLocationModeName();
|
||||||
|
}catch(Exception e){
|
||||||
|
diagnostic.logWarning("Unable to get initial location mode: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
super.initialize(cordova, webView);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called on destroying activity
|
||||||
|
*/
|
||||||
|
public void onDestroy() {
|
||||||
|
try {
|
||||||
|
diagnostic.applicationContext.unregisterReceiver(locationProviderChangedReceiver);
|
||||||
|
}catch(Exception e){
|
||||||
|
diagnostic.logWarning("Unable to unregister Location Provider Change receiver: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the request and returns PluginResult.
|
||||||
|
*
|
||||||
|
* @param action The action to execute.
|
||||||
|
* @param args JSONArry of arguments for the plugin.
|
||||||
|
* @param callbackContext The callback id used when calling back into JavaScript.
|
||||||
|
* @return True if the action was valid, false if not.
|
||||||
|
*/
|
||||||
|
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
|
||||||
|
Diagnostic.instance.currentContext = currentContext = callbackContext;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (action.equals("switchToLocationSettings")){
|
||||||
|
switchToLocationSettings();
|
||||||
|
callbackContext.success();
|
||||||
|
} else if(action.equals("isLocationAvailable")) {
|
||||||
|
callbackContext.success(isGpsLocationAvailable() || isNetworkLocationAvailable() ? 1 : 0);
|
||||||
|
} else if(action.equals("isLocationEnabled")) {
|
||||||
|
callbackContext.success(isGpsLocationEnabled() || isNetworkLocationEnabled() ? 1 : 0);
|
||||||
|
} else if(action.equals("isGpsLocationAvailable")) {
|
||||||
|
callbackContext.success(isGpsLocationAvailable() ? 1 : 0);
|
||||||
|
} else if(action.equals("isNetworkLocationAvailable")) {
|
||||||
|
callbackContext.success(isNetworkLocationAvailable() ? 1 : 0);
|
||||||
|
} else if(action.equals("isGpsLocationEnabled")) {
|
||||||
|
callbackContext.success(isGpsLocationEnabled() ? 1 : 0);
|
||||||
|
} else if(action.equals("isNetworkLocationEnabled")) {
|
||||||
|
callbackContext.success(isNetworkLocationEnabled() ? 1 : 0);
|
||||||
|
} else if(action.equals("getLocationMode")) {
|
||||||
|
callbackContext.success(getLocationModeName());
|
||||||
|
} else if(action.equals("requestLocationAuthorization")) {
|
||||||
|
requestLocationAuthorization(args, callbackContext);
|
||||||
|
}else {
|
||||||
|
diagnostic.handleError("Invalid action");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}catch(Exception e ) {
|
||||||
|
diagnostic.handleError("Exception occurred: ".concat(e.getMessage()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isGpsLocationAvailable() throws Exception {
|
||||||
|
boolean result = isGpsLocationEnabled() && isLocationAuthorized();
|
||||||
|
diagnostic.logDebug("GPS location available: " + result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isGpsLocationEnabled() throws Exception {
|
||||||
|
int mode = getLocationMode();
|
||||||
|
boolean result = (mode == 3 || mode == 1);
|
||||||
|
diagnostic.logDebug("GPS location setting enabled: " + result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNetworkLocationAvailable() throws Exception {
|
||||||
|
boolean result = isNetworkLocationEnabled() && isLocationAuthorized();
|
||||||
|
diagnostic.logDebug("Network location available: " + result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNetworkLocationEnabled() throws Exception {
|
||||||
|
int mode = getLocationMode();
|
||||||
|
boolean result = (mode == 3 || mode == 2);
|
||||||
|
diagnostic.logDebug("Network location setting enabled: " + result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLocationModeName() throws Exception {
|
||||||
|
String modeName;
|
||||||
|
int mode = getLocationMode();
|
||||||
|
switch(mode){
|
||||||
|
case Settings.Secure.LOCATION_MODE_HIGH_ACCURACY:
|
||||||
|
modeName = LOCATION_MODE_HIGH_ACCURACY;
|
||||||
|
break;
|
||||||
|
case Settings.Secure.LOCATION_MODE_SENSORS_ONLY:
|
||||||
|
modeName = LOCATION_MODE_DEVICE_ONLY;
|
||||||
|
break;
|
||||||
|
case Settings.Secure.LOCATION_MODE_BATTERY_SAVING:
|
||||||
|
modeName = LOCATION_MODE_BATTERY_SAVING;
|
||||||
|
break;
|
||||||
|
case Settings.Secure.LOCATION_MODE_OFF:
|
||||||
|
modeName = LOCATION_MODE_OFF;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
modeName = LOCATION_MODE_UNKNOWN;
|
||||||
|
}
|
||||||
|
return modeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void notifyLocationStateChange(){
|
||||||
|
try {
|
||||||
|
String newMode = getLocationModeName();
|
||||||
|
if(!newMode.equals(currentLocationMode)){
|
||||||
|
diagnostic.logDebug("Location mode change to: " + newMode);
|
||||||
|
diagnostic.executePluginJavascript("location._onLocationStateChange(\"" + newMode +"\");");
|
||||||
|
currentLocationMode = newMode;
|
||||||
|
}
|
||||||
|
}catch(Exception e){
|
||||||
|
diagnostic.logError("Error retrieving current location mode on location state change: "+e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void switchToLocationSettings() {
|
||||||
|
diagnostic.logDebug("Switch to Location Settings");
|
||||||
|
Intent settingsIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
|
||||||
|
cordova.getActivity().startActivity(settingsIntent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void requestLocationAuthorization(JSONArray args, CallbackContext callbackContext) throws Exception{
|
||||||
|
JSONArray permissionsToRequest = new JSONArray();
|
||||||
|
boolean shouldRequestBackground = args.getBoolean(0);
|
||||||
|
boolean shouldRequestPrecise = args.getBoolean(1);
|
||||||
|
|
||||||
|
permissionsToRequest.put(networkLocationPermission);
|
||||||
|
if(shouldRequestPrecise || Build.VERSION.SDK_INT < 31){
|
||||||
|
permissionsToRequest.put(gpsLocationPermission);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(shouldRequestBackground && Build.VERSION.SDK_INT >= 29 ){
|
||||||
|
permissionsToRequest.put(backgroundLocationPermission);
|
||||||
|
}
|
||||||
|
|
||||||
|
int requestId = Diagnostic.instance.storeContextByRequestId(callbackContext);
|
||||||
|
Diagnostic.instance._requestRuntimePermissions(permissionsToRequest, requestId);
|
||||||
|
|
||||||
|
PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);
|
||||||
|
result.setKeepCallback(true);
|
||||||
|
callbackContext.sendPluginResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/************
|
||||||
|
* Internals
|
||||||
|
***********/
|
||||||
|
/**
|
||||||
|
* Returns current location mode
|
||||||
|
*/
|
||||||
|
private int getLocationMode() throws Exception {
|
||||||
|
int mode;
|
||||||
|
if (Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 28){ // Kitkat to Oreo, Settings.Secute.LOCATION_MODE was deprecated in Pie (https://developer.android.com/reference/android/provider/Settings.Secure#LOCATION_MODE)
|
||||||
|
mode = Settings.Secure.getInt(this.cordova.getActivity().getContentResolver(), Settings.Secure.LOCATION_MODE);
|
||||||
|
}else{ // Pre-Kitkat and post-Oreo
|
||||||
|
if(isLocationProviderEnabled(LocationManager.GPS_PROVIDER) && isLocationProviderEnabled(LocationManager.NETWORK_PROVIDER)){
|
||||||
|
mode = 3;
|
||||||
|
} else if(isLocationProviderEnabled(LocationManager.GPS_PROVIDER)){
|
||||||
|
mode = 1;
|
||||||
|
} else if(isLocationProviderEnabled(LocationManager.NETWORK_PROVIDER)){
|
||||||
|
mode = 2;
|
||||||
|
}else{
|
||||||
|
mode = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isLocationAuthorized() throws Exception {
|
||||||
|
boolean authorized = diagnostic.hasRuntimePermission(diagnostic.permissionsMap.get(gpsLocationPermission)) || diagnostic.hasRuntimePermission(diagnostic.permissionsMap.get(networkLocationPermission));
|
||||||
|
Log.v(TAG, "Location permission is "+(authorized ? "authorized" : "unauthorized"));
|
||||||
|
return authorized;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isLocationProviderEnabled(String provider) {
|
||||||
|
return locationManager.isProviderEnabled(provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/************
|
||||||
|
* Overrides
|
||||||
|
***********/
|
||||||
|
|
||||||
|
protected final BroadcastReceiver locationProviderChangedReceiver = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
try {
|
||||||
|
final String action = intent.getAction();
|
||||||
|
if(instance != null && action.equals(LocationManager.PROVIDERS_CHANGED_ACTION)){
|
||||||
|
Log.v(TAG, "onReceiveLocationProviderChange");
|
||||||
|
instance.notifyLocationStateChange();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
diagnostic.logError("Error receiving location provider state change: "+e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Diagnostic.h
|
||||||
|
* Diagnostic Plugin - Core Module
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Working Edge Ltd.
|
||||||
|
* Copyright (c) 2012 AVANTIC ESTUDIO DE INGENIEROS
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Cordova/CDV.h>
|
||||||
|
#import <Cordova/CDVPlugin.h>
|
||||||
|
#import <WebKit/WebKit.h>
|
||||||
|
|
||||||
|
#import <mach/machine.h>
|
||||||
|
#import <sys/types.h>
|
||||||
|
#import <sys/sysctl.h>
|
||||||
|
|
||||||
|
// Public constants
|
||||||
|
extern NSString*const UNKNOWN;
|
||||||
|
|
||||||
|
extern NSString*const AUTHORIZATION_NOT_DETERMINED;
|
||||||
|
extern NSString*const AUTHORIZATION_DENIED;
|
||||||
|
extern NSString*const AUTHORIZATION_GRANTED;
|
||||||
|
extern NSString*const AUTHORIZATION_PROVISIONAL;
|
||||||
|
extern NSString*const AUTHORIZATION_EPHEMERAL;
|
||||||
|
extern NSString*const AUTHORIZATION_LIMITED;
|
||||||
|
|
||||||
|
@interface Diagnostic : CDVPlugin
|
||||||
|
|
||||||
|
@property (nonatomic) float osVersion;
|
||||||
|
@property (nonatomic) BOOL debugEnabled;
|
||||||
|
|
||||||
|
// Plugin API
|
||||||
|
- (void) enableDebug: (CDVInvokedUrlCommand*)command;
|
||||||
|
- (void) switchToSettings: (CDVInvokedUrlCommand*)command;
|
||||||
|
- (void) getBackgroundRefreshStatus: (CDVInvokedUrlCommand*)command;
|
||||||
|
- (void) getArchitecture: (CDVInvokedUrlCommand*)command;
|
||||||
|
- (void) getCurrentBatteryLevel: (CDVInvokedUrlCommand*)command;
|
||||||
|
- (void) getDeviceOSVersion: (CDVInvokedUrlCommand*)command;
|
||||||
|
- (void) getBuildOSVersion: (CDVInvokedUrlCommand*)command;
|
||||||
|
- (void) isMobileDataEnabled: (CDVInvokedUrlCommand*)command;
|
||||||
|
|
||||||
|
// Utilities
|
||||||
|
+ (id) getInstance;
|
||||||
|
- (void) sendPluginResult: (CDVPluginResult*)result :(CDVInvokedUrlCommand*)command;
|
||||||
|
- (void) sendPluginResultSuccess:(CDVInvokedUrlCommand*)command;
|
||||||
|
- (void) sendPluginNoResultAndKeepCallback:(CDVInvokedUrlCommand*)command;
|
||||||
|
- (void) sendPluginResultBool: (BOOL)result :(CDVInvokedUrlCommand*)command;
|
||||||
|
- (void) sendPluginResultString: (NSString*)result :(CDVInvokedUrlCommand*)command;
|
||||||
|
- (void) sendPluginError: (NSString*) errorMessage :(CDVInvokedUrlCommand*)command;
|
||||||
|
- (void) handlePluginException: (NSException*) exception :(CDVInvokedUrlCommand*)command;
|
||||||
|
- (void)executeGlobalJavascript: (NSString*)jsString;
|
||||||
|
- (NSString*) arrayToJsonString:(NSArray*)inputArray;
|
||||||
|
- (NSString*) objectToJsonString:(NSDictionary*)inputObject;
|
||||||
|
- (NSArray*) jsonStringToArray:(NSString*)jsonStr;
|
||||||
|
- (NSDictionary*) jsonStringToDictionary:(NSString*)jsonStr;
|
||||||
|
- (bool)isNull: (NSString*)str;
|
||||||
|
- (void)logDebug: (NSString*)msg;
|
||||||
|
- (void)logError: (NSString*)msg;
|
||||||
|
- (NSString*)escapeDoubleQuotes: (NSString*)str;
|
||||||
|
- (void) setSetting: (NSString*)key forValue:(id)value;
|
||||||
|
- (id) getSetting: (NSString*) key;
|
||||||
|
|
||||||
|
@end
|
|
@ -0,0 +1,379 @@
|
||||||
|
/*
|
||||||
|
* Diagnostic.m
|
||||||
|
* Diagnostic Plugin - Core Module
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Working Edge Ltd.
|
||||||
|
* Copyright (c) 2012 AVANTIC ESTUDIO DE INGENIEROS
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "Diagnostic.h"
|
||||||
|
#import <CoreTelephony/CTCellularData.h>
|
||||||
|
|
||||||
|
@implementation Diagnostic
|
||||||
|
|
||||||
|
// Public constants
|
||||||
|
NSString*const UNKNOWN = @"unknown";
|
||||||
|
|
||||||
|
NSString*const AUTHORIZATION_NOT_DETERMINED = @"not_determined";
|
||||||
|
NSString*const AUTHORIZATION_DENIED = @"denied_always";
|
||||||
|
NSString*const AUTHORIZATION_GRANTED = @"authorized";
|
||||||
|
NSString*const AUTHORIZATION_PROVISIONAL = @"provisional"; // Remote Notifications
|
||||||
|
NSString*const AUTHORIZATION_EPHEMERAL = @"ephemeral"; // Remote Notifications
|
||||||
|
NSString*const AUTHORIZATION_LIMITED = @"limited"; // Photo Library
|
||||||
|
|
||||||
|
// Internal constants
|
||||||
|
static NSString*const LOG_TAG = @"Diagnostic[native]";
|
||||||
|
|
||||||
|
static NSString*const CPU_ARCH_ARMv6 = @"ARMv6";
|
||||||
|
static NSString*const CPU_ARCH_ARMv7 = @"ARMv7";
|
||||||
|
static NSString*const CPU_ARCH_ARMv8 = @"ARMv8";
|
||||||
|
static NSString*const CPU_ARCH_X86 = @"X86";
|
||||||
|
static NSString*const CPU_ARCH_X86_64 = @"X86_64";
|
||||||
|
|
||||||
|
// Internal properties
|
||||||
|
static Diagnostic* diagnostic = nil;
|
||||||
|
static CTCellularData* cellularData;
|
||||||
|
|
||||||
|
/********************************/
|
||||||
|
#pragma mark - Public static functions
|
||||||
|
/********************************/
|
||||||
|
+ (id) getInstance{
|
||||||
|
return diagnostic;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/********************************/
|
||||||
|
#pragma mark - Plugin API
|
||||||
|
/********************************/
|
||||||
|
|
||||||
|
-(void)enableDebug:(CDVInvokedUrlCommand*)command{
|
||||||
|
self.debugEnabled = true;
|
||||||
|
[self logDebug:@"Debug enabled"];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Settings
|
||||||
|
- (void) switchToSettings: (CDVInvokedUrlCommand*)command
|
||||||
|
{
|
||||||
|
@try {
|
||||||
|
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: UIApplicationOpenSettingsURLString] options:@{} completionHandler:^(BOOL success) {
|
||||||
|
if (success) {
|
||||||
|
[self sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK] :command];
|
||||||
|
}else{
|
||||||
|
[self sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR] :command];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
@catch (NSException *exception) {
|
||||||
|
[self handlePluginException:exception :command];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Background refresh
|
||||||
|
- (void) getBackgroundRefreshStatus: (CDVInvokedUrlCommand*)command
|
||||||
|
{
|
||||||
|
UIBackgroundRefreshStatus _status;
|
||||||
|
@try {
|
||||||
|
// Must run on UI thread
|
||||||
|
_status = [[UIApplication sharedApplication] backgroundRefreshStatus];
|
||||||
|
}@catch (NSException *exception) {
|
||||||
|
[self handlePluginException:exception :command];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
[self.commandDelegate runInBackground:^{
|
||||||
|
@try {
|
||||||
|
NSString* status;
|
||||||
|
|
||||||
|
if (_status == UIBackgroundRefreshStatusAvailable) {
|
||||||
|
status = AUTHORIZATION_GRANTED;
|
||||||
|
[self logDebug:@"Background updates are available for the app."];
|
||||||
|
}else if(_status == UIBackgroundRefreshStatusDenied){
|
||||||
|
status = AUTHORIZATION_DENIED;
|
||||||
|
[self logDebug:@"The user explicitly disabled background behavior for this app or for the whole system."];
|
||||||
|
}else if(_status == UIBackgroundRefreshStatusRestricted){
|
||||||
|
status = @"restricted";
|
||||||
|
[self logDebug:@"Background updates are unavailable and the user cannot enable them again. For example, this status can occur when parental controls are in effect for the current user."];
|
||||||
|
}
|
||||||
|
[self sendPluginResultString:status:command];
|
||||||
|
}
|
||||||
|
@catch (NSException *exception) {
|
||||||
|
[self handlePluginException:exception :command];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/********************************/
|
||||||
|
#pragma mark - Internal functions
|
||||||
|
/********************************/
|
||||||
|
|
||||||
|
- (void)pluginInitialize {
|
||||||
|
|
||||||
|
[super pluginInitialize];
|
||||||
|
|
||||||
|
diagnostic = self;
|
||||||
|
|
||||||
|
self.debugEnabled = false;
|
||||||
|
self.osVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
|
||||||
|
cellularData = [[CTCellularData alloc] init];
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://stackoverflow.com/a/38441011/777265
|
||||||
|
- (void) getArchitecture: (CDVInvokedUrlCommand*)command {
|
||||||
|
[self.commandDelegate runInBackground:^{
|
||||||
|
@try {
|
||||||
|
NSString* cpuArch = UNKNOWN;
|
||||||
|
|
||||||
|
size_t size;
|
||||||
|
cpu_type_t type;
|
||||||
|
cpu_subtype_t subtype;
|
||||||
|
size = sizeof(type);
|
||||||
|
sysctlbyname("hw.cputype", &type, &size, NULL, 0);
|
||||||
|
|
||||||
|
size = sizeof(subtype);
|
||||||
|
sysctlbyname("hw.cpusubtype", &subtype, &size, NULL, 0);
|
||||||
|
|
||||||
|
// values for cputype and cpusubtype defined in mach/machine.h
|
||||||
|
if (type == CPU_TYPE_X86_64) {
|
||||||
|
cpuArch = CPU_ARCH_X86_64;
|
||||||
|
} else if (type == CPU_TYPE_X86) {
|
||||||
|
cpuArch = CPU_ARCH_X86;
|
||||||
|
} else if (type == CPU_TYPE_ARM64) {
|
||||||
|
cpuArch = CPU_ARCH_ARMv8;
|
||||||
|
} else if (type == CPU_TYPE_ARM) {
|
||||||
|
switch(subtype){
|
||||||
|
case CPU_SUBTYPE_ARM_V6:
|
||||||
|
cpuArch = CPU_ARCH_ARMv6;
|
||||||
|
break;
|
||||||
|
case CPU_SUBTYPE_ARM_V7:
|
||||||
|
cpuArch = CPU_ARCH_ARMv7;
|
||||||
|
break;
|
||||||
|
case CPU_SUBTYPE_ARM_V8:
|
||||||
|
cpuArch = CPU_ARCH_ARMv8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[self logDebug:[NSString stringWithFormat:@"Current CPU architecture: %@", cpuArch]];
|
||||||
|
[self sendPluginResultString:cpuArch:command];
|
||||||
|
}@catch (NSException *exception) {
|
||||||
|
[self handlePluginException:exception :command];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) getCurrentBatteryLevel: (CDVInvokedUrlCommand*)command {
|
||||||
|
[self.commandDelegate runInBackground:^{
|
||||||
|
@try {
|
||||||
|
UIDevice* currentDevice = [UIDevice currentDevice];
|
||||||
|
[currentDevice setBatteryMonitoringEnabled:true];
|
||||||
|
int batteryLevel = (int)([currentDevice batteryLevel]*100);
|
||||||
|
[self logDebug:[NSString stringWithFormat:@"Battery level: %d", batteryLevel]];
|
||||||
|
[self sendPluginResultInt:batteryLevel:command];
|
||||||
|
[currentDevice setBatteryMonitoringEnabled:false];
|
||||||
|
}@catch (NSException *exception) {
|
||||||
|
[self handlePluginException:exception :command];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) getDeviceOSVersion: (CDVInvokedUrlCommand*)command {
|
||||||
|
[self.commandDelegate runInBackground:^{
|
||||||
|
@try {
|
||||||
|
NSString* s_version = [UIDevice currentDevice].systemVersion;
|
||||||
|
float f_version = [s_version floatValue];
|
||||||
|
|
||||||
|
NSDictionary* details = @{
|
||||||
|
@"version": s_version,
|
||||||
|
@"apiLevel" : [NSNumber numberWithFloat:f_version*10000],
|
||||||
|
@"apiName": s_version
|
||||||
|
};
|
||||||
|
|
||||||
|
[self sendPluginResultObject:details:command];
|
||||||
|
}@catch (NSException *exception) {
|
||||||
|
[self handlePluginException:exception :command];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) getBuildOSVersion: (CDVInvokedUrlCommand*)command {
|
||||||
|
[self.commandDelegate runInBackground:^{
|
||||||
|
@try {
|
||||||
|
int i_min_version = __IPHONE_OS_VERSION_MIN_REQUIRED;
|
||||||
|
NSString* s_min_version = [NSString stringWithFormat:@"%.01f", (float) i_min_version/10000];
|
||||||
|
int i_target_version = __IPHONE_OS_VERSION_MAX_ALLOWED;
|
||||||
|
NSString* s_target_version = [NSString stringWithFormat:@"%.01f", (float) i_target_version/10000];
|
||||||
|
|
||||||
|
NSDictionary* details = @{
|
||||||
|
@"targetApiLevel": [NSNumber numberWithInt:i_target_version],
|
||||||
|
@"targetApiName": s_target_version,
|
||||||
|
@"minApiLevel": [NSNumber numberWithInt:i_min_version],
|
||||||
|
@"minApiName": s_min_version
|
||||||
|
};
|
||||||
|
|
||||||
|
[self sendPluginResultObject:details:command];
|
||||||
|
}@catch (NSException *exception) {
|
||||||
|
[self handlePluginException:exception :command];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) isMobileDataEnabled: (CDVInvokedUrlCommand*)command
|
||||||
|
{
|
||||||
|
[self.commandDelegate runInBackground:^{
|
||||||
|
@try {
|
||||||
|
bool isEnabled = cellularData.restrictedState == kCTCellularDataNotRestricted;;
|
||||||
|
[diagnostic sendPluginResultBool:isEnabled :command];
|
||||||
|
}
|
||||||
|
@catch (NSException *exception) {
|
||||||
|
[diagnostic handlePluginException:exception :command];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/********************************/
|
||||||
|
#pragma mark - Send results
|
||||||
|
/********************************/
|
||||||
|
|
||||||
|
- (void) sendPluginResult: (CDVPluginResult*)result :(CDVInvokedUrlCommand*)command
|
||||||
|
{
|
||||||
|
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) sendPluginResultSuccess:(CDVInvokedUrlCommand*)command{
|
||||||
|
[self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK] callbackId:command.callbackId];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) sendPluginNoResultAndKeepCallback:(CDVInvokedUrlCommand*)command {
|
||||||
|
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_NO_RESULT];
|
||||||
|
[pluginResult setKeepCallbackAsBool:YES];
|
||||||
|
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) sendPluginResultBool: (BOOL)result :(CDVInvokedUrlCommand*)command
|
||||||
|
{
|
||||||
|
CDVPluginResult* pluginResult;
|
||||||
|
if(result) {
|
||||||
|
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:1];
|
||||||
|
} else {
|
||||||
|
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:0];
|
||||||
|
}
|
||||||
|
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) sendPluginResultString: (NSString*)result :(CDVInvokedUrlCommand*)command
|
||||||
|
{
|
||||||
|
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:result];
|
||||||
|
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) sendPluginResultInt: (int)result :(CDVInvokedUrlCommand*)command
|
||||||
|
{
|
||||||
|
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:result];
|
||||||
|
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) sendPluginResultObject: (NSDictionary*)result :(CDVInvokedUrlCommand*)command
|
||||||
|
{
|
||||||
|
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:result];
|
||||||
|
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) sendPluginError: (NSString*) errorMessage :(CDVInvokedUrlCommand*)command
|
||||||
|
{
|
||||||
|
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:errorMessage];
|
||||||
|
[self logError:errorMessage];
|
||||||
|
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) handlePluginException: (NSException*) exception :(CDVInvokedUrlCommand*)command
|
||||||
|
{
|
||||||
|
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:exception.reason];
|
||||||
|
[self logError:[NSString stringWithFormat:@"EXCEPTION: %@", exception.reason]];
|
||||||
|
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)executeGlobalJavascript: (NSString*)jsString
|
||||||
|
{
|
||||||
|
[self.commandDelegate evalJs:jsString];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString*) arrayToJsonString:(NSArray*)inputArray
|
||||||
|
{
|
||||||
|
NSError* error;
|
||||||
|
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:inputArray options:NSJSONWritingPrettyPrinted error:&error];
|
||||||
|
NSString* jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||||
|
jsonString = [[jsonString componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]] componentsJoinedByString:@""];
|
||||||
|
return jsonString;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString*) objectToJsonString:(NSDictionary*)inputObject
|
||||||
|
{
|
||||||
|
NSError* error;
|
||||||
|
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:inputObject options:NSJSONWritingPrettyPrinted error:&error];
|
||||||
|
NSString* jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||||
|
return jsonString;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray*) jsonStringToArray:(NSString*)jsonStr
|
||||||
|
{
|
||||||
|
NSError* error = nil;
|
||||||
|
NSArray* array = [NSJSONSerialization JSONObjectWithData:[jsonStr dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:&error];
|
||||||
|
if (error != nil){
|
||||||
|
array = nil;
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSDictionary*) jsonStringToDictionary:(NSString*)jsonStr
|
||||||
|
{
|
||||||
|
return (NSDictionary*) [self jsonStringToArray:jsonStr];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (bool)isNull: (NSString*)str
|
||||||
|
{
|
||||||
|
return str == nil || str == (id)[NSNull null] || str.length == 0 || [str isEqual: @"<null>"];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/********************************/
|
||||||
|
#pragma mark - utility functions
|
||||||
|
/********************************/
|
||||||
|
|
||||||
|
- (void)logDebug: (NSString*)msg
|
||||||
|
{
|
||||||
|
if(self.debugEnabled){
|
||||||
|
NSLog(@"%@: %@", LOG_TAG, msg);
|
||||||
|
NSString* jsString = [NSString stringWithFormat:@"console.log(\"%@: %@\")", LOG_TAG, [self escapeDoubleQuotes:msg]];
|
||||||
|
[self executeGlobalJavascript:jsString];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)logError: (NSString*)msg
|
||||||
|
{
|
||||||
|
NSLog(@"%@ ERROR: %@", LOG_TAG, msg);
|
||||||
|
if(self.debugEnabled){
|
||||||
|
NSString* jsString = [NSString stringWithFormat:@"console.error(\"%@: %@\")", LOG_TAG, [self escapeDoubleQuotes:msg]];
|
||||||
|
[self executeGlobalJavascript:jsString];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString*)escapeDoubleQuotes: (NSString*)str
|
||||||
|
{
|
||||||
|
NSString *result =[str stringByReplacingOccurrencesOfString: @"\"" withString: @"\\\""];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setSetting: (NSString*)key forValue:(id)value
|
||||||
|
{
|
||||||
|
[[NSUserDefaults standardUserDefaults] setObject:value forKey:key];
|
||||||
|
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) getSetting: (NSString*) key
|
||||||
|
{
|
||||||
|
return [[NSUserDefaults standardUserDefaults] objectForKey:key];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Diagnostic_Location.h
|
||||||
|
* Diagnostic Plugin - Location Module
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018 Working Edge Ltd.
|
||||||
|
* Copyright (c) 2012 AVANTIC ESTUDIO DE INGENIEROS
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Cordova/CDV.h>
|
||||||
|
#import <Cordova/CDVPlugin.h>
|
||||||
|
#import "Diagnostic.h"
|
||||||
|
#import <CoreLocation/CoreLocation.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@interface Diagnostic_Location : CDVPlugin <CLLocationManagerDelegate>
|
||||||
|
|
||||||
|
@property (strong, nonatomic) CLLocationManager* locationManager;
|
||||||
|
@property (nonatomic, retain) NSString* locationRequestCallbackId;
|
||||||
|
@property (nonatomic, retain) NSString* currentLocationAuthorizationStatus;
|
||||||
|
@property (nonatomic, retain) NSString* currentLocationAccuracyAuthorization;
|
||||||
|
|
||||||
|
- (void) isLocationAvailable: (CDVInvokedUrlCommand*)command;
|
||||||
|
- (void) isLocationEnabled: (CDVInvokedUrlCommand*)command;
|
||||||
|
- (void) isLocationAuthorized: (CDVInvokedUrlCommand*)command;
|
||||||
|
- (void) getLocationAuthorizationStatus: (CDVInvokedUrlCommand*)command;
|
||||||
|
- (void) getLocationAccuracyAuthorization: (CDVInvokedUrlCommand*)command;
|
||||||
|
- (void) requestLocationAuthorization: (CDVInvokedUrlCommand*)command;
|
||||||
|
- (void) requestTemporaryFullAccuracyAuthorization: (CDVInvokedUrlCommand*)command;
|
||||||
|
|
||||||
|
@end
|
|
@ -0,0 +1,286 @@
|
||||||
|
/*
|
||||||
|
* Diagnostic_Location.m
|
||||||
|
* Diagnostic Plugin - Location Module
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018 Working Edge Ltd.
|
||||||
|
* Copyright (c) 2012 AVANTIC ESTUDIO DE INGENIEROS
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "Diagnostic_Location.h"
|
||||||
|
|
||||||
|
@implementation Diagnostic_Location
|
||||||
|
|
||||||
|
// Internal reference to Diagnostic singleton instance
|
||||||
|
static Diagnostic* diagnostic;
|
||||||
|
|
||||||
|
// Internal constants
|
||||||
|
static NSString*const LOG_TAG = @"Diagnostic_Location[native]";
|
||||||
|
|
||||||
|
|
||||||
|
/********************************/
|
||||||
|
#pragma mark - Plugin API
|
||||||
|
/********************************/
|
||||||
|
|
||||||
|
- (void) isLocationAvailable: (CDVInvokedUrlCommand*)command
|
||||||
|
{
|
||||||
|
[self.commandDelegate runInBackground:^{
|
||||||
|
@try {
|
||||||
|
[diagnostic sendPluginResultBool:[CLLocationManager locationServicesEnabled] && [self isLocationAuthorized] :command];
|
||||||
|
}
|
||||||
|
@catch (NSException *exception) {
|
||||||
|
[diagnostic handlePluginException:exception :command];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) isLocationEnabled: (CDVInvokedUrlCommand*)command
|
||||||
|
{
|
||||||
|
[self.commandDelegate runInBackground:^{
|
||||||
|
@try {
|
||||||
|
[diagnostic sendPluginResultBool:[CLLocationManager locationServicesEnabled] :command];
|
||||||
|
}
|
||||||
|
@catch (NSException *exception) {
|
||||||
|
[diagnostic handlePluginException:exception :command];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (void) isLocationAuthorized: (CDVInvokedUrlCommand*)command
|
||||||
|
{
|
||||||
|
[self.commandDelegate runInBackground:^{
|
||||||
|
@try {
|
||||||
|
[diagnostic sendPluginResultBool:[self isLocationAuthorized] :command];
|
||||||
|
}
|
||||||
|
@catch (NSException *exception) {
|
||||||
|
[diagnostic handlePluginException:exception :command];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) getLocationAuthorizationStatus: (CDVInvokedUrlCommand*)command
|
||||||
|
{
|
||||||
|
[self.commandDelegate runInBackground:^{
|
||||||
|
@try {
|
||||||
|
NSString* status = [self getLocationAuthorizationStatusAsString:[self getAuthorizationStatus]];
|
||||||
|
[diagnostic logDebug:[NSString stringWithFormat:@"Location authorization status is: %@", status]];
|
||||||
|
[diagnostic sendPluginResultString:status:command];
|
||||||
|
}
|
||||||
|
@catch (NSException *exception) {
|
||||||
|
[diagnostic handlePluginException:exception :command];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) requestLocationAuthorization: (CDVInvokedUrlCommand*)command
|
||||||
|
{
|
||||||
|
[self.commandDelegate runInBackground:^{
|
||||||
|
@try {
|
||||||
|
if ([CLLocationManager instancesRespondToSelector:@selector(requestWhenInUseAuthorization)])
|
||||||
|
{
|
||||||
|
BOOL always = [[command argumentAtIndex:0] boolValue];
|
||||||
|
if(always){
|
||||||
|
NSAssert([[[NSBundle mainBundle] infoDictionary] valueForKey:@"NSLocationAlwaysAndWhenInUseUsageDescription"], @"Your app must have a value for NSLocationAlwaysAndWhenInUseUsageDescription in its Info.plist");
|
||||||
|
[self.locationManager requestAlwaysAuthorization];
|
||||||
|
[diagnostic logDebug:@"Requesting location authorization: always"];
|
||||||
|
}else{
|
||||||
|
NSAssert([[[NSBundle mainBundle] infoDictionary] valueForKey:@"NSLocationWhenInUseUsageDescription"], @"Your app must have a value for NSLocationWhenInUseUsageDescription in its Info.plist");
|
||||||
|
[self.locationManager requestWhenInUseAuthorization];
|
||||||
|
[diagnostic logDebug:@"Requesting location authorization: when in use"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@catch (NSException *exception) {
|
||||||
|
[diagnostic handlePluginException:exception :command];
|
||||||
|
}
|
||||||
|
self.locationRequestCallbackId = command.callbackId;
|
||||||
|
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_NO_RESULT];
|
||||||
|
[pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
|
||||||
|
[diagnostic sendPluginResult:pluginResult :command];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) getLocationAccuracyAuthorization: (CDVInvokedUrlCommand*)command{
|
||||||
|
[self.commandDelegate runInBackground:^{
|
||||||
|
@try {
|
||||||
|
|
||||||
|
#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0
|
||||||
|
if ([CLLocationManager instancesRespondToSelector:@selector(requestTemporaryFullAccuracyAuthorizationWithPurposeKey:completion:)]){
|
||||||
|
NSString* locationAccuracyAuthorization = [self getLocationAccuracyAuthorizationAsString:[self.locationManager accuracyAuthorization]];
|
||||||
|
[diagnostic logDebug:[NSString stringWithFormat:@"Location accuracy authorization is: %@", locationAccuracyAuthorization]];
|
||||||
|
[diagnostic sendPluginResultString:locationAccuracyAuthorization:command];
|
||||||
|
}else{
|
||||||
|
[diagnostic logDebug:@"Location accuracy authorization is not available on device running iOS <14"];
|
||||||
|
[diagnostic sendPluginResultString:@"full":command];
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
[diagnostic logDebug:@"Location accuracy authorization is not available in builds with iOS SDK <14"];
|
||||||
|
[diagnostic sendPluginResultString:@"full":command];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
@catch (NSException *exception) {
|
||||||
|
[diagnostic handlePluginException:exception :command];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) requestTemporaryFullAccuracyAuthorization: (CDVInvokedUrlCommand*)command{
|
||||||
|
[self.commandDelegate runInBackground:^{
|
||||||
|
@try {
|
||||||
|
|
||||||
|
#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0
|
||||||
|
if ([CLLocationManager instancesRespondToSelector:@selector(requestTemporaryFullAccuracyAuthorizationWithPurposeKey:completion:)]){
|
||||||
|
NSAssert([[[NSBundle mainBundle] infoDictionary] valueForKey:@"NSLocationTemporaryUsageDescriptionDictionary"], @"For iOS 14 and above, your app must have a value for NSLocationTemporaryUsageDescriptionDictionary in its Info.plist");
|
||||||
|
NSString* purpose = [command argumentAtIndex:0];
|
||||||
|
[self.locationManager requestTemporaryFullAccuracyAuthorizationWithPurposeKey:purpose completion:^(NSError* error){
|
||||||
|
if(error != nil){
|
||||||
|
[diagnostic sendPluginError:[NSString stringWithFormat:@"Error when requesting temporary full location accuracy authorization: %@", error] :command];
|
||||||
|
}else{
|
||||||
|
NSString* locationAccuracyAuthorization = [self getLocationAccuracyAuthorizationAsString:[self.locationManager accuracyAuthorization]];
|
||||||
|
[diagnostic sendPluginResultString:locationAccuracyAuthorization :command];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}else{
|
||||||
|
[diagnostic sendPluginError:@"requestTemporaryFullAccuracyAuthorization is not available on device running iOS <14":command];
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
[diagnostic sendPluginError:@"requestTemporaryFullAccuracyAuthorization is not available in builds with iOS SDK <14":command];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
@catch (NSException *exception) {
|
||||||
|
[diagnostic handlePluginException:exception :command];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************/
|
||||||
|
#pragma mark - Internals
|
||||||
|
/********************************/
|
||||||
|
|
||||||
|
- (void)pluginInitialize {
|
||||||
|
|
||||||
|
[super pluginInitialize];
|
||||||
|
|
||||||
|
diagnostic = [Diagnostic getInstance];
|
||||||
|
|
||||||
|
self.locationRequestCallbackId = nil;
|
||||||
|
self.currentLocationAuthorizationStatus = nil;
|
||||||
|
self.locationManager = [[CLLocationManager alloc] init];
|
||||||
|
self.locationManager.delegate = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString*) getLocationAuthorizationStatusAsString: (CLAuthorizationStatus)authStatus
|
||||||
|
{
|
||||||
|
NSString* status;
|
||||||
|
if(authStatus == kCLAuthorizationStatusDenied || authStatus == kCLAuthorizationStatusRestricted){
|
||||||
|
status = AUTHORIZATION_DENIED;
|
||||||
|
}else if(authStatus == kCLAuthorizationStatusNotDetermined){
|
||||||
|
status = AUTHORIZATION_NOT_DETERMINED;
|
||||||
|
}else if(authStatus == kCLAuthorizationStatusAuthorizedAlways){
|
||||||
|
status = AUTHORIZATION_GRANTED;
|
||||||
|
}else if(authStatus == kCLAuthorizationStatusAuthorizedWhenInUse){
|
||||||
|
status = @"authorized_when_in_use";
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0
|
||||||
|
- (NSString*) getLocationAccuracyAuthorizationAsString: (CLAccuracyAuthorization)accuracyAuthorization
|
||||||
|
{
|
||||||
|
NSString* accuracy;
|
||||||
|
if(accuracyAuthorization == CLAccuracyAuthorizationFullAccuracy){
|
||||||
|
accuracy = @"full";
|
||||||
|
}else{
|
||||||
|
accuracy = @"reduced";
|
||||||
|
}
|
||||||
|
return accuracy;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
- (BOOL) isLocationAuthorized
|
||||||
|
{
|
||||||
|
CLAuthorizationStatus authStatus = [self getAuthorizationStatus];
|
||||||
|
NSString* status = [self getLocationAuthorizationStatusAsString:authStatus];
|
||||||
|
if([status isEqual: AUTHORIZATION_GRANTED] || [status isEqual: @"authorized_when_in_use"]) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-(CLAuthorizationStatus) getAuthorizationStatus{
|
||||||
|
CLAuthorizationStatus authStatus;
|
||||||
|
#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0
|
||||||
|
if ([CLLocationManager instancesRespondToSelector:@selector(authorizationStatus)]){
|
||||||
|
authStatus = [self.locationManager authorizationStatus];
|
||||||
|
}else{
|
||||||
|
authStatus = [CLLocationManager authorizationStatus];
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
authStatus = [CLLocationManager authorizationStatus];
|
||||||
|
#endif
|
||||||
|
return authStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0
|
||||||
|
// Note: if built with Xcode >=12 (iOS >=14 SDK) but device is running on iOS <=13, this will not be invoked
|
||||||
|
-(void)locationManagerDidChangeAuthorization:(CLLocationManager *)manager{
|
||||||
|
// Location authorization status
|
||||||
|
[self reportChangeAuthorizationStatus:[self.locationManager authorizationStatus]];
|
||||||
|
|
||||||
|
// Location accuracy authorization
|
||||||
|
NSString* locationAccuracyAuthorization = [self getLocationAccuracyAuthorizationAsString:[self.locationManager accuracyAuthorization]];
|
||||||
|
BOOL locationAccuracyAuthorizationChanged = false;
|
||||||
|
if(self.currentLocationAccuracyAuthorization != nil && ![locationAccuracyAuthorization isEqual: self.currentLocationAccuracyAuthorization]){
|
||||||
|
locationAccuracyAuthorizationChanged = true;
|
||||||
|
}
|
||||||
|
self.currentLocationAccuracyAuthorization = locationAccuracyAuthorization;
|
||||||
|
|
||||||
|
if(locationAccuracyAuthorizationChanged){
|
||||||
|
[diagnostic logDebug:[NSString stringWithFormat:@"Location accuracy authorization changed to: %@", locationAccuracyAuthorization]];
|
||||||
|
|
||||||
|
[diagnostic executeGlobalJavascript:[NSString stringWithFormat:@"cordova.plugins.diagnostic.location._onLocationAccuracyAuthorizationChange(\"%@\");", locationAccuracyAuthorization]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)authStatus {
|
||||||
|
#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0
|
||||||
|
if ([CLLocationManager instancesRespondToSelector:@selector(authorizationStatus)]){
|
||||||
|
// Build SDK & device using iOS >=14 so locationManagerDidChangeAuthorization will be invoked
|
||||||
|
}else{
|
||||||
|
// Build SDK using iOS >=14 but device running iOS <=13
|
||||||
|
[self reportChangeAuthorizationStatus:authStatus];
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// Device may be running iOS >=14 but build SDK is iOS <=13
|
||||||
|
[self reportChangeAuthorizationStatus:authStatus];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (void)reportChangeAuthorizationStatus:(CLAuthorizationStatus)authStatus{
|
||||||
|
|
||||||
|
NSString* locationAuthorizationStatus = [self getLocationAuthorizationStatusAsString:authStatus];
|
||||||
|
BOOL locationAuthorizationStatusChanged = false;
|
||||||
|
if(self.currentLocationAuthorizationStatus != nil && ![locationAuthorizationStatus isEqual: self.currentLocationAuthorizationStatus]){
|
||||||
|
locationAuthorizationStatusChanged = true;
|
||||||
|
}
|
||||||
|
self.currentLocationAuthorizationStatus = locationAuthorizationStatus;
|
||||||
|
|
||||||
|
if(locationAuthorizationStatusChanged){
|
||||||
|
[diagnostic logDebug:[NSString stringWithFormat:@"Location authorization status changed to: %@", locationAuthorizationStatus]];
|
||||||
|
|
||||||
|
if(self.locationRequestCallbackId != nil){
|
||||||
|
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:locationAuthorizationStatus];
|
||||||
|
[self.commandDelegate sendPluginResult:pluginResult callbackId:self.locationRequestCallbackId];
|
||||||
|
self.locationRequestCallbackId = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
[diagnostic executeGlobalJavascript:[NSString stringWithFormat:@"cordova.plugins.diagnostic.location._onLocationStateChange(\"%@\");", locationAuthorizationStatus]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* Diagnostic_Microphone.h
|
||||||
|
* Diagnostic Plugin - Microphone Module
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018 Working Edge Ltd.
|
||||||
|
* Copyright (c) 2012 AVANTIC ESTUDIO DE INGENIEROS
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Cordova/CDV.h>
|
||||||
|
#import <Cordova/CDVPlugin.h>
|
||||||
|
#import "Diagnostic.h"
|
||||||
|
|
||||||
|
#import <AVFoundation/AVFoundation.h>
|
||||||
|
|
||||||
|
@interface Diagnostic_Microphone : CDVPlugin
|
||||||
|
|
||||||
|
- (void) isMicrophoneAuthorized: (CDVInvokedUrlCommand*)command;
|
||||||
|
- (void) getMicrophoneAuthorizationStatus: (CDVInvokedUrlCommand*)command;
|
||||||
|
- (void) requestMicrophoneAuthorization: (CDVInvokedUrlCommand*)command;
|
||||||
|
|
||||||
|
@end
|
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
* Diagnostic_Microphone.m
|
||||||
|
* Diagnostic Plugin - Microphone Module
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018 Working Edge Ltd.
|
||||||
|
* Copyright (c) 2012 AVANTIC ESTUDIO DE INGENIEROS
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "Diagnostic_Microphone.h"
|
||||||
|
|
||||||
|
@implementation Diagnostic_Microphone
|
||||||
|
|
||||||
|
// Internal reference to Diagnostic singleton instance
|
||||||
|
static Diagnostic* diagnostic;
|
||||||
|
|
||||||
|
// Internal constants
|
||||||
|
static NSString*const LOG_TAG = @"Diagnostic_Microphone[native]";
|
||||||
|
|
||||||
|
- (void)pluginInitialize {
|
||||||
|
|
||||||
|
[super pluginInitialize];
|
||||||
|
|
||||||
|
diagnostic = [Diagnostic getInstance];
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************/
|
||||||
|
#pragma mark - Plugin API
|
||||||
|
/********************************/
|
||||||
|
|
||||||
|
- (void) isMicrophoneAuthorized: (CDVInvokedUrlCommand*)command
|
||||||
|
{
|
||||||
|
[self.commandDelegate runInBackground:^{
|
||||||
|
CDVPluginResult* pluginResult;
|
||||||
|
@try {
|
||||||
|
AVAudioSessionRecordPermission recordPermission = [AVAudioSession sharedInstance].recordPermission;
|
||||||
|
|
||||||
|
if(recordPermission == AVAudioSessionRecordPermissionGranted) {
|
||||||
|
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:1];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:0];
|
||||||
|
}
|
||||||
|
[diagnostic sendPluginResultBool:recordPermission == AVAudioSessionRecordPermissionGranted :command];
|
||||||
|
}
|
||||||
|
@catch (NSException *exception) {
|
||||||
|
[diagnostic handlePluginException:exception :command];
|
||||||
|
};
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) getMicrophoneAuthorizationStatus: (CDVInvokedUrlCommand*)command
|
||||||
|
{
|
||||||
|
[self.commandDelegate runInBackground:^{
|
||||||
|
@try {
|
||||||
|
NSString* status;
|
||||||
|
AVAudioSessionRecordPermission recordPermission = [AVAudioSession sharedInstance].recordPermission;
|
||||||
|
switch(recordPermission){
|
||||||
|
case AVAudioSessionRecordPermissionDenied:
|
||||||
|
status = AUTHORIZATION_DENIED;
|
||||||
|
break;
|
||||||
|
case AVAudioSessionRecordPermissionGranted:
|
||||||
|
status = AUTHORIZATION_GRANTED;
|
||||||
|
break;
|
||||||
|
case AVAudioSessionRecordPermissionUndetermined:
|
||||||
|
status = AUTHORIZATION_NOT_DETERMINED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
[diagnostic logDebug:[NSString stringWithFormat:@"Microphone authorization status is: %@", status]];
|
||||||
|
[diagnostic sendPluginResultString:status:command];
|
||||||
|
}
|
||||||
|
@catch (NSException *exception) {
|
||||||
|
[diagnostic handlePluginException:exception :command];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) requestMicrophoneAuthorization: (CDVInvokedUrlCommand*)command
|
||||||
|
{
|
||||||
|
[self.commandDelegate runInBackground:^{
|
||||||
|
@try {
|
||||||
|
[[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
|
||||||
|
[diagnostic logDebug:[NSString stringWithFormat:@"Has access to microphone: %d", granted]];
|
||||||
|
[diagnostic sendPluginResultBool:granted :command];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
@catch (NSException *exception) {
|
||||||
|
[diagnostic handlePluginException:exception :command];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************/
|
||||||
|
#pragma mark - Internals
|
||||||
|
/********************************/
|
||||||
|
|
||||||
|
@end
|
Loading…
Reference in New Issue