Get bridge working, get geolocation working
This commit is contained in:
parent
9102d6ef87
commit
b165ec6005
8 changed files with 261 additions and 25 deletions
|
@ -9,7 +9,7 @@ android {
|
|||
|
||||
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
|
||||
dependencies {
|
||||
implementation project(':capacitor-geolocation')
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -11,41 +11,44 @@ import com.getcapacitor.annotation.CapacitorPlugin;
|
|||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
@CapacitorPlugin(name = "Echo")
|
||||
@CapacitorPlugin(name = "Databridge")
|
||||
public class Databridge extends Plugin {
|
||||
|
||||
private final Map<String, Consumer<PluginCall>> responders;
|
||||
private static final Map<String, Consumer<PluginCall>> responders = new HashMap<>();
|
||||
static {
|
||||
responders.put("meta", Databridge.answer("capacitator-shell 0.0.1;"));
|
||||
}
|
||||
|
||||
private static Consumer<PluginCall> answer(String answer) {
|
||||
return (PluginCall call) -> Databridge.sendAnswerTo(call, answer);
|
||||
}
|
||||
|
||||
public static void sendAnswerTo(PluginCall call, String answer) {
|
||||
JSObject ret = new JSObject();
|
||||
ret.put("value", answer);
|
||||
Log.i("databridge","Resolving call");
|
||||
return (PluginCall call) -> call.resolve(ret);
|
||||
Log.i("databridge", "Resolving call");
|
||||
call.resolve(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* A responder will be activated if the native code asks for it.
|
||||
* Use call.setKeepAlive(true) for multiple responses
|
||||
* @param responders
|
||||
* Use call.setKeepAlive(true) if the responder will send multiple responses
|
||||
*/
|
||||
public Databridge(Map<String, Consumer<PluginCall>> responders) {
|
||||
this.responders = responders;
|
||||
responders.put("meta", Databridge.answer("capacitator-shell 0.0.1;"));
|
||||
public static void addResponder(String key, Consumer<PluginCall> responder) {
|
||||
responders.put(key, responder);
|
||||
}
|
||||
|
||||
@PluginMethod()
|
||||
public void request(PluginCall call) {
|
||||
String key = call.getString("key");
|
||||
Log.i("databridge","Got a call: "+key);
|
||||
var c= this.responders.get(key);
|
||||
if(c != null){
|
||||
Log.i("databridge", "Got a call: " + key);
|
||||
var c = this.responders.get(key);
|
||||
if (c != null) {
|
||||
c.accept(call);
|
||||
}else{
|
||||
call.reject("ERROR: no responder installed for "+key);
|
||||
} else {
|
||||
call.reject("ERROR: no responder installed for " + key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
155
app/src/main/java/org/mapcomplete/GeolocationBridge.java
Normal file
155
app/src/main/java/org/mapcomplete/GeolocationBridge.java
Normal file
|
@ -0,0 +1,155 @@
|
|||
package org.mapcomplete;
|
||||
|
||||
import android.content.Context;
|
||||
import android.location.Location;
|
||||
import android.location.LocationListener;
|
||||
import android.location.LocationManager;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.core.location.LocationManagerCompat;
|
||||
|
||||
import com.getcapacitor.JSObject;
|
||||
import com.getcapacitor.PluginCall;
|
||||
|
||||
public class GeolocationBridge {
|
||||
|
||||
public static final int requestCode = 684198;
|
||||
|
||||
private final Context context;
|
||||
private final MainActivity mainActivity;
|
||||
|
||||
GeolocationBridge(Context context, MainActivity mainActivity) {
|
||||
this.context = context;
|
||||
this.mainActivity = mainActivity;
|
||||
|
||||
Databridge.addResponder("location:watch", pluginCall -> {
|
||||
pluginCall.setKeepAlive(true);
|
||||
new LocationUpdateListener(pluginCall, context).requestLocationUpdates(true);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class LocationUpdateListener implements LocationListener {
|
||||
|
||||
private final PluginCall callback;
|
||||
private final Context context;
|
||||
|
||||
public LocationUpdateListener(PluginCall callback, Context context) {
|
||||
this.callback = callback;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
private void answer(String answer) {
|
||||
Databridge.sendAnswerTo(this.callback, answer);
|
||||
}
|
||||
|
||||
private void error(String msg) {
|
||||
this.callback.reject(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the location manager to indicate what providers are available.
|
||||
* Typical providers are `passive`, `network`, `fused` and `gps`
|
||||
* <p>
|
||||
* This method selects the best appropriate
|
||||
*/
|
||||
private String getPreferredProvider(boolean enableHighAccuracy) {
|
||||
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
|
||||
var providers = lm.getProviders(true);
|
||||
if (enableHighAccuracy) {
|
||||
if (providers.contains("gps")) {
|
||||
return "gps";
|
||||
}
|
||||
if (providers.contains("fused")) {
|
||||
return "fused";
|
||||
}
|
||||
if (providers.contains("network")) {
|
||||
return "network";
|
||||
}
|
||||
} else {
|
||||
if (providers.contains("network")) {
|
||||
return "network";
|
||||
}
|
||||
if (providers.contains("fused")) {
|
||||
return "fused";
|
||||
}
|
||||
if (providers.contains("gps")) {
|
||||
return "gps";
|
||||
}
|
||||
}
|
||||
if (providers.contains("passive")) {
|
||||
return "passive";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private Boolean isLocationServicesEnabled() {
|
||||
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
|
||||
return LocationManagerCompat.isLocationEnabled(lm);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("MissingPermission")
|
||||
public void requestLocationUpdates(boolean enableHighAccuracy) {
|
||||
|
||||
if (!this.isLocationServicesEnabled()) {
|
||||
this.error("location disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
|
||||
|
||||
var provider = getPreferredProvider(enableHighAccuracy);
|
||||
if (provider == null) {
|
||||
this.error("Location unavailable: no providers defined. Note: this is a Google Play Services free implementation");
|
||||
return;
|
||||
}
|
||||
lm.requestLocationUpdates(provider, 1000, 10, this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onLocationChanged(Location location) {
|
||||
JSObject loc = new JSObject();
|
||||
loc.put("latitude", location.getLatitude());
|
||||
loc.put("longitude", location.getLongitude());
|
||||
if (location.hasAccuracy()) {
|
||||
loc.put("accuracy", location.getAccuracy());
|
||||
}
|
||||
if (location.hasAltitude()) {
|
||||
loc.put("altitude", location.getAltitude());
|
||||
}
|
||||
if (location.hasBearing()) {
|
||||
// Expected for heading: 0 is north, 90 is east, up till 359° ; see https://developer.mozilla.org/en-US/docs/Web/API/GeolocationCoordinates
|
||||
// getBearing returns essentially the same
|
||||
loc.put("heading", location.getBearing());
|
||||
}
|
||||
|
||||
JSObject ret = new JSObject();
|
||||
ret.put("value", loc);
|
||||
Log.i("databridge", "Resolving call");
|
||||
this.callback.resolve(ret);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusChanged(String provider, int status, Bundle extras) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderEnabled(String provider) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderDisabled(String provider) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,15 +1,98 @@
|
|||
package org.mapcomplete;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.getcapacitor.BridgeActivity;
|
||||
import com.getcapacitor.JSObject;
|
||||
import com.getcapacitor.Plugin;
|
||||
import com.getcapacitor.PluginCall;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class MainActivity extends BridgeActivity {
|
||||
|
||||
private PluginCall locationRequest = null;
|
||||
private PluginCall authRequest = null;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
registerPlugin(Databridge.class);
|
||||
new GeolocationBridge(getApplicationContext(), this);
|
||||
Databridge.addResponder("location:request-permission", pluginCall -> {
|
||||
this.locationRequest = pluginCall;
|
||||
this.requestPermission();
|
||||
});
|
||||
Databridge.addResponder("request:login", pluginCall -> {
|
||||
this.authRequest = pluginCall;
|
||||
});
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
private void requestPermission() {
|
||||
|
||||
if (ContextCompat.checkSelfPermission(
|
||||
getApplicationContext(),
|
||||
android.Manifest.permission.ACCESS_FINE_LOCATION
|
||||
) != PackageManager.PERMISSION_GRANTED) {
|
||||
// Permission is not granted, request it
|
||||
ActivityCompat.requestPermissions(
|
||||
this,
|
||||
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
|
||||
GeolocationBridge.requestCode
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
if (!Intent.ACTION_VIEW.equals(intent.getAction())) {
|
||||
return;
|
||||
}
|
||||
Uri url = intent.getData();
|
||||
if (url == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Objects.equals(url.getPath(), "/land.html")) {
|
||||
var code = url.getQueryParameter("code");
|
||||
var state = url.getQueryParameter("state");
|
||||
JSObject obj = new JSObject();
|
||||
obj.put("code", code);
|
||||
obj.put("state", state);
|
||||
JSObject res = new JSObject();
|
||||
res.put("value", obj);
|
||||
Log.i("main", "Resolving auth call");
|
||||
this.authRequest.resolve(res);
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println("Intercepted URL: " + url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(
|
||||
int requestCode,
|
||||
String[] permissions,
|
||||
int[] grantResults
|
||||
) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
if (requestCode == GeolocationBridge.requestCode) {
|
||||
if (this.locationRequest != null) {
|
||||
// We've only requested "FINE_LOCATION"
|
||||
var granted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
|
||||
Log.i("Geolocation", "Got fine location request: " + granted);
|
||||
Databridge.sendAnswerTo(this.locationRequest, granted ? "granted" : "denied");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<paths>
|
||||
<external-path name="my_images" path="." />
|
||||
<cache-path name="my_cache_images" path="." />
|
||||
</paths>
|
||||
</paths>
|
||||
|
|
|
@ -8,7 +8,6 @@ buildscript {
|
|||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:8.2.1'
|
||||
classpath 'com.google.gms:google-services:4.4.0'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
|
||||
include ':capacitor-android'
|
||||
project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor')
|
||||
|
||||
include ':capacitor-geolocation'
|
||||
project(':capacitor-geolocation').projectDir = new File('../node_modules/@capacitor/geolocation/android')
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue