Open Google Maps on Google devices
This commit is contained in:
parent
3ac332535d
commit
73f597fb54
17
.idea/deploymentTargetDropDown.xml
Normal file
17
.idea/deploymentTargetDropDown.xml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="deploymentTargetDropDown">
|
||||||
|
<runningDeviceTargetSelectedWithDropDown>
|
||||||
|
<Target>
|
||||||
|
<type value="RUNNING_DEVICE_TARGET" />
|
||||||
|
<deviceKey>
|
||||||
|
<Key>
|
||||||
|
<type value="VIRTUAL_DEVICE_PATH" />
|
||||||
|
<value value="$USER_HOME$/.android/avd/Nexus_4_API_30.avd" />
|
||||||
|
</Key>
|
||||||
|
</deviceKey>
|
||||||
|
</Target>
|
||||||
|
</runningDeviceTargetSelectedWithDropDown>
|
||||||
|
<timeTargetWasSelectedWithDropDown value="2022-02-23T20:43:47.864894Z" />
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -21,10 +21,13 @@
|
|||||||
package="it.danieleverducci.nextcloudmaps">
|
package="it.danieleverducci.nextcloudmaps">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
|
|
||||||
<queries>
|
<queries>
|
||||||
<package android:name="com.nextcloud.client" />
|
<package android:name="com.nextcloud.client" />
|
||||||
|
<!-- To see if google maps is installed, as it needs a specific intent Uri) -->
|
||||||
|
<package android:name="com.google.android.apps.maps" />
|
||||||
</queries>
|
</queries>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
|
@ -161,7 +161,7 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple
|
|||||||
if (getIntent().getData() != null) {
|
if (getIntent().getData() != null) {
|
||||||
// Opened by external generic intent: parse URI
|
// Opened by external generic intent: parse URI
|
||||||
try {
|
try {
|
||||||
double[] coords = GeoUriParser.parseUri(getIntent().getData());
|
double[] coords = GeoUriParser.parseUri(getIntent().getData(), false);
|
||||||
mGeofavorite.setLat(coords[0]);
|
mGeofavorite.setLat(coords[0]);
|
||||||
mGeofavorite.setLng(coords[1]);
|
mGeofavorite.setLng(coords[1]);
|
||||||
mViewHolder.hideAccuracy();
|
mViewHolder.hideAccuracy();
|
||||||
|
@ -15,25 +15,19 @@ import android.view.inputmethod.InputMethodManager;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.core.app.ActivityCompat;
|
import androidx.core.app.ActivityCompat;
|
||||||
import androidx.preference.PreferenceManager;
|
|
||||||
|
|
||||||
import org.osmdroid.api.IGeoPoint;
|
import org.osmdroid.api.IGeoPoint;
|
||||||
import org.osmdroid.api.IMapController;
|
import org.osmdroid.api.IMapController;
|
||||||
import org.osmdroid.config.Configuration;
|
|
||||||
import org.osmdroid.config.IConfigurationProvider;
|
|
||||||
import org.osmdroid.events.MapListener;
|
import org.osmdroid.events.MapListener;
|
||||||
import org.osmdroid.events.ScrollEvent;
|
import org.osmdroid.events.ScrollEvent;
|
||||||
import org.osmdroid.events.ZoomEvent;
|
import org.osmdroid.events.ZoomEvent;
|
||||||
import org.osmdroid.util.GeoPoint;
|
import org.osmdroid.util.GeoPoint;
|
||||||
import org.osmdroid.views.CustomZoomButtonsController;
|
import org.osmdroid.views.CustomZoomButtonsController;
|
||||||
import org.osmdroid.views.MapView;
|
import org.osmdroid.views.MapView;
|
||||||
import org.osmdroid.views.Projection;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import it.danieleverducci.nextcloudmaps.BuildConfig;
|
|
||||||
import it.danieleverducci.nextcloudmaps.R;
|
import it.danieleverducci.nextcloudmaps.R;
|
||||||
import it.danieleverducci.nextcloudmaps.activity.NextcloudMapsStyledActivity;
|
import it.danieleverducci.nextcloudmaps.activity.NextcloudMapsStyledActivity;
|
||||||
import it.danieleverducci.nextcloudmaps.activity.detail.GeofavoriteDetailActivity;
|
import it.danieleverducci.nextcloudmaps.activity.detail.GeofavoriteDetailActivity;
|
||||||
@ -64,7 +58,7 @@ public class MapPickerActivity extends NextcloudMapsStyledActivity {
|
|||||||
@Override
|
@Override
|
||||||
public void onConfirmButtonPressed() {
|
public void onConfirmButtonPressed() {
|
||||||
double[] coords = mViewHolder.getCurrentCoordinates();
|
double[] coords = mViewHolder.getCurrentCoordinates();
|
||||||
Uri geoUri = GeoUriParser.createUri(coords[0], coords[1], null);
|
Uri geoUri = GeoUriParser.createGeoUri(coords[0], coords[1], null);
|
||||||
Intent i = new Intent(MapPickerActivity.this, GeofavoriteDetailActivity.class);
|
Intent i = new Intent(MapPickerActivity.this, GeofavoriteDetailActivity.class);
|
||||||
i.setData(geoUri);
|
i.setData(geoUri);
|
||||||
startActivity(i);
|
startActivity(i);
|
||||||
|
@ -164,7 +164,10 @@ public class Geofavorite implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Uri getGeoUri() {
|
public Uri getGeoUri() {
|
||||||
return GeoUriParser.createUri(this.lat, this.lng, this.name);
|
return GeoUriParser.createGeoUri(this.lat, this.lng, this.name);
|
||||||
|
}
|
||||||
|
public Uri getGmapsUri() {
|
||||||
|
return GeoUriParser.createGmapsUri(this.lat, this.lng);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean valid() {
|
public boolean valid() {
|
||||||
|
@ -10,35 +10,79 @@ import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
|||||||
|
|
||||||
public class GeoUriParser {
|
public class GeoUriParser {
|
||||||
private static final Pattern PATTERN_GEO = Pattern.compile("geo:(-?[\\d.]+),(-?[\\d.]+)");
|
private static final Pattern PATTERN_GEO = Pattern.compile("geo:(-?[\\d.]+),(-?[\\d.]+)");
|
||||||
|
// Try to match not only geoUri but also Google Maps Uri
|
||||||
|
private static final Pattern PATTERN_BROAD = Pattern.compile(
|
||||||
|
"(?:&query=|¢er=|geo:)(-?\\d{1,2}\\.\\d{1,10})(?:,|%2C)(-?\\d{1,3}\\.\\d{1,10})"
|
||||||
|
);
|
||||||
|
|
||||||
public static double[] parseUri(Uri uri) throws IllegalArgumentException {
|
/**
|
||||||
|
* Parses an URI into latitude and longitude
|
||||||
|
* @param uri to parse
|
||||||
|
* @param strict if true, the uri must be a valid geo: uri, otherwise a broader check is applied to include other uris, like Google Maps ones
|
||||||
|
* @return the parsed coordinates in an array [lat,lon]
|
||||||
|
* @throws IllegalArgumentException if the url could not be parsed
|
||||||
|
*/
|
||||||
|
public static double[] parseUri(Uri uri, boolean strict) throws IllegalArgumentException {
|
||||||
if (uri == null)
|
if (uri == null)
|
||||||
throw new IllegalArgumentException("no uri");
|
throw new IllegalArgumentException("no uri");
|
||||||
|
|
||||||
Matcher m = PATTERN_GEO.matcher(uri.toString());
|
// Try to extract coordinates in uri string with regexp
|
||||||
if (m.find() && m.groupCount() == 2) {
|
Pattern pattern = strict ? PATTERN_GEO : PATTERN_BROAD;
|
||||||
String sLat = m.group(1);
|
Matcher m = pattern.matcher(uri.toString());
|
||||||
String sLon = m.group(2);
|
if (!m.find() || m.groupCount() != 2)
|
||||||
try {
|
throw new IllegalArgumentException("unable to parse uri: unable to find coordinates in uri");
|
||||||
return new double[]{Double.parseDouble(sLat), Double.parseDouble(sLon)};
|
|
||||||
} catch (NumberFormatException e) {
|
// Obtain coordinates from regexp result
|
||||||
throw new IllegalArgumentException("unable to parse uri");
|
String sLat = m.group(1);
|
||||||
}
|
String sLon = m.group(2);
|
||||||
} else {
|
double[] coords = null;
|
||||||
throw new IllegalArgumentException("unable to parse uri");
|
try {
|
||||||
|
// Check coordinates are numeric
|
||||||
|
coords = new double[]{Double.parseDouble(sLat), Double.parseDouble(sLon)};
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new IllegalArgumentException("unable to parse uri: coordinates are not double");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check coordinates validity
|
||||||
|
String error = checkCoordsValidity(coords[0], coords[1]);
|
||||||
|
if (error != null)
|
||||||
|
throw new IllegalArgumentException(error);
|
||||||
|
|
||||||
|
return coords;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Uri createUri(double lat, double lon, String name) {
|
public static Uri createGeoUri(double lat, double lon, String name) {
|
||||||
// Check coords validity
|
String error = checkCoordsValidity(lat, lon);
|
||||||
if (lon <= -180 || lon >= 180 )
|
if (error != null)
|
||||||
throw new IllegalArgumentException("Invalid longitude: " + lon);
|
throw new IllegalArgumentException(error);
|
||||||
if (lat <= -90 || lat >= 90)
|
|
||||||
throw new IllegalArgumentException("Invalid latitude: " + lat);
|
|
||||||
|
|
||||||
String uriStr = "geo:" + lat + "," + lon;
|
String uriStr = "geo:" + lat + "," + lon;
|
||||||
if (name != null)
|
if (name != null)
|
||||||
uriStr += "(" + name + ")";
|
uriStr += "(" + name + ")";
|
||||||
return Uri.parse(uriStr);
|
return Uri.parse(uriStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Uri createGmapsUri(double lat, double lon) {
|
||||||
|
String error = checkCoordsValidity(lat, lon);
|
||||||
|
if (error != null)
|
||||||
|
throw new IllegalArgumentException(error);
|
||||||
|
|
||||||
|
String uriStr = "https://www.google.com/maps/search/?api=1&query=" + lat + "," + lon;
|
||||||
|
return Uri.parse(uriStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks a latitude/longitude is valid
|
||||||
|
* @param lat latitude
|
||||||
|
* @param lon longitude
|
||||||
|
* @return null if valid, a string containing an error otherwise
|
||||||
|
*/
|
||||||
|
private static String checkCoordsValidity(double lat, double lon) {
|
||||||
|
// Check coords validity
|
||||||
|
if (lon <= -180 || lon >= 180 )
|
||||||
|
return "Invalid longitude: " + lon;
|
||||||
|
if (lat <= -90 || lat >= 90)
|
||||||
|
return "Invalid latitude: " + lat;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
package it.danieleverducci.nextcloudmaps.utils;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.net.Uri;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Google maps doesn't honor geouri standard, instead implements its own uri.
|
|
||||||
* A geouri opens google maps, but the position is ignored, so it is needed to use gmaps own uri.
|
|
||||||
* Utility to check if gmaps is installed and generate a gmaps uri
|
|
||||||
*/
|
|
||||||
public class GoogleMapsUri {
|
|
||||||
|
|
||||||
public static boolean isGoogleMapsInstalled(Context context) {
|
|
||||||
try {
|
|
||||||
context.getPackageManager().getApplicationInfo("com.google.android.apps.maps", 0);
|
|
||||||
return true;
|
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Uri createGmapsUri(double lat, double lon) {
|
|
||||||
// Check coords validity
|
|
||||||
if (lon <= -180 || lon >= 180 )
|
|
||||||
throw new IllegalArgumentException("Invalid longitude: " + lon);
|
|
||||||
if (lat <= -90 || lat >= 90)
|
|
||||||
throw new IllegalArgumentException("Invalid latitude: " + lat);
|
|
||||||
|
|
||||||
String uriStr = "https://www.google.com/maps/search/?api=1&query=" + lat + "," + lon;
|
|
||||||
return Uri.parse(uriStr);
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,6 +2,7 @@ package it.danieleverducci.nextcloudmaps.utils;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import it.danieleverducci.nextcloudmaps.R;
|
import it.danieleverducci.nextcloudmaps.R;
|
||||||
@ -22,7 +23,16 @@ public class IntentGenerator {
|
|||||||
public static Intent newGeoUriIntent(Context context, Geofavorite item) {
|
public static Intent newGeoUriIntent(Context context, Geofavorite item) {
|
||||||
Intent i = new Intent();
|
Intent i = new Intent();
|
||||||
i.setAction(Intent.ACTION_VIEW);
|
i.setAction(Intent.ACTION_VIEW);
|
||||||
i.setData(item.getGeoUri());
|
i.setData(isGoogleMapsInstalled(context) ? item.getGmapsUri() : item.getGeoUri());
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isGoogleMapsInstalled(Context context) {
|
||||||
|
try {
|
||||||
|
context.getPackageManager().getApplicationInfo("com.google.android.apps.maps", 0);
|
||||||
|
return true;
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user