Open Google Maps on Google devices
This commit is contained in:
		@@ -21,10 +21,13 @@
 | 
			
		||||
    package="it.danieleverducci.nextcloudmaps">
 | 
			
		||||
 | 
			
		||||
    <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" />
 | 
			
		||||
 | 
			
		||||
    <queries>
 | 
			
		||||
        <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>
 | 
			
		||||
 | 
			
		||||
    <application
 | 
			
		||||
 
 | 
			
		||||
@@ -161,7 +161,7 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple
 | 
			
		||||
            if (getIntent().getData() != null) {
 | 
			
		||||
                // Opened by external generic intent: parse URI
 | 
			
		||||
                try {
 | 
			
		||||
                    double[] coords = GeoUriParser.parseUri(getIntent().getData());
 | 
			
		||||
                    double[] coords = GeoUriParser.parseUri(getIntent().getData(), false);
 | 
			
		||||
                    mGeofavorite.setLat(coords[0]);
 | 
			
		||||
                    mGeofavorite.setLng(coords[1]);
 | 
			
		||||
                    mViewHolder.hideAccuracy();
 | 
			
		||||
 
 | 
			
		||||
@@ -15,25 +15,19 @@ import android.view.inputmethod.InputMethodManager;
 | 
			
		||||
import android.widget.Toast;
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.Nullable;
 | 
			
		||||
import androidx.appcompat.app.AppCompatActivity;
 | 
			
		||||
import androidx.core.app.ActivityCompat;
 | 
			
		||||
import androidx.preference.PreferenceManager;
 | 
			
		||||
 | 
			
		||||
import org.osmdroid.api.IGeoPoint;
 | 
			
		||||
import org.osmdroid.api.IMapController;
 | 
			
		||||
import org.osmdroid.config.Configuration;
 | 
			
		||||
import org.osmdroid.config.IConfigurationProvider;
 | 
			
		||||
import org.osmdroid.events.MapListener;
 | 
			
		||||
import org.osmdroid.events.ScrollEvent;
 | 
			
		||||
import org.osmdroid.events.ZoomEvent;
 | 
			
		||||
import org.osmdroid.util.GeoPoint;
 | 
			
		||||
import org.osmdroid.views.CustomZoomButtonsController;
 | 
			
		||||
import org.osmdroid.views.MapView;
 | 
			
		||||
import org.osmdroid.views.Projection;
 | 
			
		||||
 | 
			
		||||
import java.util.Locale;
 | 
			
		||||
 | 
			
		||||
import it.danieleverducci.nextcloudmaps.BuildConfig;
 | 
			
		||||
import it.danieleverducci.nextcloudmaps.R;
 | 
			
		||||
import it.danieleverducci.nextcloudmaps.activity.NextcloudMapsStyledActivity;
 | 
			
		||||
import it.danieleverducci.nextcloudmaps.activity.detail.GeofavoriteDetailActivity;
 | 
			
		||||
@@ -64,7 +58,7 @@ public class MapPickerActivity extends NextcloudMapsStyledActivity {
 | 
			
		||||
            @Override
 | 
			
		||||
            public void onConfirmButtonPressed() {
 | 
			
		||||
                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);
 | 
			
		||||
                i.setData(geoUri);
 | 
			
		||||
                startActivity(i);
 | 
			
		||||
 
 | 
			
		||||
@@ -164,7 +164,10 @@ public class Geofavorite implements Serializable {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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() {
 | 
			
		||||
 
 | 
			
		||||
@@ -10,35 +10,79 @@ import it.danieleverducci.nextcloudmaps.model.Geofavorite;
 | 
			
		||||
 | 
			
		||||
public class GeoUriParser {
 | 
			
		||||
    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)
 | 
			
		||||
            throw new IllegalArgumentException("no uri");
 | 
			
		||||
 | 
			
		||||
        Matcher m = PATTERN_GEO.matcher(uri.toString());
 | 
			
		||||
        if (m.find() && m.groupCount() == 2) {
 | 
			
		||||
            String sLat = m.group(1);
 | 
			
		||||
            String sLon = m.group(2);
 | 
			
		||||
            try {
 | 
			
		||||
                return new double[]{Double.parseDouble(sLat), Double.parseDouble(sLon)};
 | 
			
		||||
            } catch (NumberFormatException e) {
 | 
			
		||||
                throw new IllegalArgumentException("unable to parse uri");
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new IllegalArgumentException("unable to parse uri");
 | 
			
		||||
        // Try to extract coordinates in uri string with regexp
 | 
			
		||||
        Pattern pattern = strict ? PATTERN_GEO : PATTERN_BROAD;
 | 
			
		||||
        Matcher m = pattern.matcher(uri.toString());
 | 
			
		||||
        if (!m.find() || m.groupCount() != 2)
 | 
			
		||||
            throw new IllegalArgumentException("unable to parse uri: unable to find coordinates in uri");
 | 
			
		||||
 | 
			
		||||
        // Obtain coordinates from regexp result
 | 
			
		||||
        String sLat = m.group(1);
 | 
			
		||||
        String sLon = m.group(2);
 | 
			
		||||
        double[] coords = null;
 | 
			
		||||
        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) {
 | 
			
		||||
        // 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);
 | 
			
		||||
    public static Uri createGeoUri(double lat, double lon, String name) {
 | 
			
		||||
        String error = checkCoordsValidity(lat, lon);
 | 
			
		||||
        if (error != null)
 | 
			
		||||
            throw new IllegalArgumentException(error);
 | 
			
		||||
 | 
			
		||||
        String uriStr = "geo:" + lat + "," + lon;
 | 
			
		||||
        if (name != null)
 | 
			
		||||
            uriStr += "(" + name + ")";
 | 
			
		||||
        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.Intent;
 | 
			
		||||
import android.content.pm.PackageManager;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
 | 
			
		||||
import it.danieleverducci.nextcloudmaps.R;
 | 
			
		||||
@@ -22,7 +23,16 @@ public class IntentGenerator {
 | 
			
		||||
    public static Intent newGeoUriIntent(Context context, Geofavorite item) {
 | 
			
		||||
        Intent i = new Intent();
 | 
			
		||||
        i.setAction(Intent.ACTION_VIEW);
 | 
			
		||||
        i.setData(item.getGeoUri());
 | 
			
		||||
        i.setData(isGoogleMapsInstalled(context) ? item.getGmapsUri() : item.getGeoUri());
 | 
			
		||||
        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;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user