2
0
Fork 0
Vmeda.Online/cordova-plugin-moodleapp/src/android/Diagnostic_Location.java

319 lines
12 KiB
Java

// (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());
}
}
};
}