Open Google Maps on Google devices
This commit is contained in:
		
							
								
								
									
										17
									
								
								.idea/deploymentTargetDropDown.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								.idea/deploymentTargetDropDown.xml
									
									
									
										generated
									
									
									
										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"> | ||||
|  | ||||
|     <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