use internal location viewer for in text geo uris
This commit is contained in:
parent
a3cc91dc11
commit
e950d431bc
|
@ -236,13 +236,11 @@ public abstract class LocationActivity extends ActionBarActivity implements Loca
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.M)
|
|
||||||
protected boolean hasLocationPermissions() {
|
protected boolean hasLocationPermissions() {
|
||||||
return (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED ||
|
return (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED ||
|
||||||
checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED);
|
checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.M)
|
|
||||||
protected void requestPermissions(final int request_code) {
|
protected void requestPermissions(final int request_code) {
|
||||||
if (!hasLocationPermissions()) {
|
if (!hasLocationPermissions()) {
|
||||||
requestPermissions(
|
requestPermissions(
|
||||||
|
|
|
@ -9,6 +9,7 @@ import android.location.Location;
|
||||||
import android.location.LocationListener;
|
import android.location.LocationListener;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -17,11 +18,8 @@ import android.widget.Toast;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.databinding.DataBindingUtil;
|
import androidx.databinding.DataBindingUtil;
|
||||||
|
|
||||||
import org.osmdroid.util.GeoPoint;
|
import com.google.common.base.Strings;
|
||||||
|
import com.google.common.primitives.Doubles;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
|
@ -30,8 +28,13 @@ import eu.siacs.conversations.ui.util.LocationHelper;
|
||||||
import eu.siacs.conversations.ui.util.UriHelper;
|
import eu.siacs.conversations.ui.util.UriHelper;
|
||||||
import eu.siacs.conversations.ui.widget.Marker;
|
import eu.siacs.conversations.ui.widget.Marker;
|
||||||
import eu.siacs.conversations.ui.widget.MyLocation;
|
import eu.siacs.conversations.ui.widget.MyLocation;
|
||||||
|
import eu.siacs.conversations.utils.GeoHelper;
|
||||||
import eu.siacs.conversations.utils.LocationProvider;
|
import eu.siacs.conversations.utils.LocationProvider;
|
||||||
|
|
||||||
|
import org.osmdroid.util.GeoPoint;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class ShowLocationActivity extends LocationActivity implements LocationListener {
|
public class ShowLocationActivity extends LocationActivity implements LocationListener {
|
||||||
|
|
||||||
private GeoPoint loc = LocationProvider.FALLBACK;
|
private GeoPoint loc = LocationProvider.FALLBACK;
|
||||||
|
@ -56,73 +59,41 @@ public class ShowLocationActivity extends LocationActivity implements LocationLi
|
||||||
this.binding.fab.setOnClickListener(view -> startNavigation());
|
this.binding.fab.setOnClickListener(view -> startNavigation());
|
||||||
|
|
||||||
final Intent intent = getIntent();
|
final Intent intent = getIntent();
|
||||||
if (intent != null) {
|
if (intent == null) {
|
||||||
final String action = intent.getAction();
|
return;
|
||||||
if (action == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (action) {
|
|
||||||
case "eu.siacs.conversations.location.show":
|
|
||||||
if (intent.hasExtra("longitude") && intent.hasExtra("latitude")) {
|
|
||||||
final double longitude = intent.getDoubleExtra("longitude", 0);
|
|
||||||
final double latitude = intent.getDoubleExtra("latitude", 0);
|
|
||||||
this.loc = new GeoPoint(latitude, longitude);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Intent.ACTION_VIEW:
|
|
||||||
final Uri geoUri = intent.getData();
|
|
||||||
|
|
||||||
// Attempt to set zoom level if the geo URI specifies it
|
|
||||||
if (geoUri != null) {
|
|
||||||
final HashMap<String, String> query =
|
|
||||||
UriHelper.parseQueryString(geoUri.getQuery());
|
|
||||||
|
|
||||||
// Check for zoom level.
|
|
||||||
final String z = query.get("z");
|
|
||||||
if (z != null) {
|
|
||||||
try {
|
|
||||||
mapController.setZoom(Double.valueOf(z));
|
|
||||||
} catch (final Exception ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for the actual geo query.
|
|
||||||
boolean posInQuery = false;
|
|
||||||
final String q = query.get("q");
|
|
||||||
if (q != null) {
|
|
||||||
final Pattern latlng =
|
|
||||||
Pattern.compile(
|
|
||||||
"/^([-+]?[0-9]+(\\.[0-9]+)?),([-+]?[0-9]+(\\.[0-9]+)?)(\\(.*\\))?/");
|
|
||||||
final Matcher m = latlng.matcher(q);
|
|
||||||
if (m.matches()) {
|
|
||||||
try {
|
|
||||||
this.loc =
|
|
||||||
new GeoPoint(
|
|
||||||
Double.valueOf(m.group(1)),
|
|
||||||
Double.valueOf(m.group(3)));
|
|
||||||
posInQuery = true;
|
|
||||||
} catch (final Exception ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final String schemeSpecificPart = geoUri.getSchemeSpecificPart();
|
|
||||||
if (schemeSpecificPart != null && !schemeSpecificPart.isEmpty()) {
|
|
||||||
try {
|
|
||||||
final GeoPoint latlong =
|
|
||||||
LocationHelper.parseLatLong(schemeSpecificPart);
|
|
||||||
if (latlong != null && !posInQuery) {
|
|
||||||
this.loc = latlong;
|
|
||||||
}
|
|
||||||
} catch (final NumberFormatException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
updateLocationMarkers();
|
|
||||||
}
|
}
|
||||||
|
final String action = intent.getAction();
|
||||||
|
switch (Strings.nullToEmpty(action)) {
|
||||||
|
case "eu.siacs.conversations.location.show":
|
||||||
|
if (intent.hasExtra("longitude") && intent.hasExtra("latitude")) {
|
||||||
|
final double longitude = intent.getDoubleExtra("longitude", 0);
|
||||||
|
final double latitude = intent.getDoubleExtra("latitude", 0);
|
||||||
|
this.loc = new GeoPoint(latitude, longitude);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Intent.ACTION_VIEW:
|
||||||
|
final Uri uri = intent.getData();
|
||||||
|
if (uri == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
final GeoPoint point;
|
||||||
|
try {
|
||||||
|
point = GeoHelper.parseGeoPoint(uri);
|
||||||
|
} catch (final Exception e) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this.loc = point;
|
||||||
|
final Map<String, String> query = UriHelper.parseQueryString(uri.getQuery());
|
||||||
|
final String z = query.get("z");
|
||||||
|
final Double zoom = Strings.isNullOrEmpty(z) ? null : Doubles.tryParse(z);
|
||||||
|
if (zoom != null) {
|
||||||
|
Log.d(Config.LOGTAG, "inferring zoom level " + zoom + " from geo uri");
|
||||||
|
mapController.setZoom(zoom);
|
||||||
|
gotoLoc(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
updateLocationMarkers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -173,37 +144,43 @@ public class ShowLocationActivity extends LocationActivity implements LocationLi
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
final var itemId = item.getItemId();
|
||||||
case R.id.action_copy_location:
|
if (itemId == R.id.action_copy_location) {
|
||||||
final ClipboardManager clipboard =
|
final ClipboardManager clipboard = getSystemService(ClipboardManager.class);
|
||||||
(ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
|
final ClipData clip = ClipData.newPlainText("location", createGeoUri().toString());
|
||||||
if (clipboard != null) {
|
clipboard.setPrimaryClip(clip);
|
||||||
final ClipData clip =
|
Toast.makeText(this, R.string.url_copied_to_clipboard, Toast.LENGTH_SHORT).show();
|
||||||
ClipData.newPlainText("location", createGeoUri().toString());
|
return true;
|
||||||
clipboard.setPrimaryClip(clip);
|
} else if (itemId == R.id.action_share_location) {
|
||||||
Toast.makeText(this, R.string.url_copied_to_clipboard, Toast.LENGTH_SHORT)
|
final Intent shareIntent = new Intent();
|
||||||
.show();
|
shareIntent.setAction(Intent.ACTION_SEND);
|
||||||
}
|
shareIntent.putExtra(Intent.EXTRA_TEXT, createGeoUri().toString());
|
||||||
return true;
|
shareIntent.setType("text/plain");
|
||||||
case R.id.action_share_location:
|
try {
|
||||||
final Intent shareIntent = new Intent();
|
startActivity(Intent.createChooser(shareIntent, getText(R.string.share_with)));
|
||||||
shareIntent.setAction(Intent.ACTION_SEND);
|
} catch (final ActivityNotFoundException e) {
|
||||||
shareIntent.putExtra(Intent.EXTRA_TEXT, createGeoUri().toString());
|
// This should happen only on faulty androids because normally chooser is always
|
||||||
shareIntent.setType("text/plain");
|
// available
|
||||||
try {
|
Toast.makeText(this, R.string.no_application_found_to_open_file, Toast.LENGTH_SHORT)
|
||||||
startActivity(Intent.createChooser(shareIntent, getText(R.string.share_with)));
|
.show();
|
||||||
} catch (final ActivityNotFoundException e) {
|
}
|
||||||
// This should happen only on faulty androids because normally chooser is always
|
return true;
|
||||||
// available
|
} else if (itemId == R.id.action_open_with) {
|
||||||
Toast.makeText(
|
final Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||||
this,
|
intent.setData(createGeoUri());
|
||||||
R.string.no_application_found_to_open_file,
|
try {
|
||||||
Toast.LENGTH_SHORT)
|
startActivity(Intent.createChooser(intent, getText(R.string.open_with)));
|
||||||
.show();
|
} catch (final ActivityNotFoundException e) {
|
||||||
}
|
// This should happen only on faulty androids because normally chooser is always
|
||||||
return true;
|
// available
|
||||||
|
Toast.makeText(this, R.string.no_application_found_to_open_file, Toast.LENGTH_SHORT)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startNavigation() {
|
private void startNavigation() {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
@ -20,16 +21,19 @@ import androidx.core.widget.ImageViewCompat;
|
||||||
import androidx.databinding.DataBindingUtil;
|
import androidx.databinding.DataBindingUtil;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.databinding.ItemMediaPreviewBinding;
|
import eu.siacs.conversations.databinding.ItemMediaPreviewBinding;
|
||||||
import eu.siacs.conversations.persistance.FileBackend;
|
import eu.siacs.conversations.persistance.FileBackend;
|
||||||
import eu.siacs.conversations.ui.ConversationFragment;
|
import eu.siacs.conversations.ui.ConversationFragment;
|
||||||
|
import eu.siacs.conversations.ui.ShowLocationActivity;
|
||||||
import eu.siacs.conversations.ui.XmppActivity;
|
import eu.siacs.conversations.ui.XmppActivity;
|
||||||
import eu.siacs.conversations.ui.util.Attachment;
|
import eu.siacs.conversations.ui.util.Attachment;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
|
|
||||||
public class MediaPreviewAdapter
|
public class MediaPreviewAdapter
|
||||||
|
@ -73,11 +77,16 @@ public class MediaPreviewAdapter
|
||||||
holder.binding.mediaPreview.setOnClickListener(v -> view(context, attachment));
|
holder.binding.mediaPreview.setOnClickListener(v -> view(context, attachment));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void view(final Context context, Attachment attachment) {
|
private static void view(final Context context, final Attachment attachment) {
|
||||||
final Intent view = new Intent(Intent.ACTION_VIEW);
|
final Intent view = new Intent(Intent.ACTION_VIEW);
|
||||||
final Uri uri = FileBackend.getUriForUri(context, attachment.getUri());
|
if (attachment.getType() == Attachment.Type.LOCATION) {
|
||||||
view.setDataAndType(uri, attachment.getMime());
|
view.setClass(context, ShowLocationActivity.class);
|
||||||
view.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
view.setData(attachment.getUri());
|
||||||
|
} else {
|
||||||
|
final Uri uri = FileBackend.getUriForUri(context, attachment.getUri());
|
||||||
|
view.setDataAndType(uri, attachment.getMime());
|
||||||
|
view.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
context.startActivity(view);
|
context.startActivity(view);
|
||||||
} catch (final ActivityNotFoundException e) {
|
} catch (final ActivityNotFoundException e) {
|
||||||
|
|
|
@ -38,6 +38,7 @@ import android.os.Build;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.style.URLSpan;
|
import android.text.style.URLSpan;
|
||||||
|
import android.view.SoundEffectConstants;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
@ -45,43 +46,56 @@ import java.util.Arrays;
|
||||||
|
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.ui.ConversationsActivity;
|
import eu.siacs.conversations.ui.ConversationsActivity;
|
||||||
|
import eu.siacs.conversations.ui.ShowLocationActivity;
|
||||||
|
|
||||||
@SuppressLint("ParcelCreator")
|
@SuppressLint("ParcelCreator")
|
||||||
public class FixedURLSpan extends URLSpan {
|
public class FixedURLSpan extends URLSpan {
|
||||||
|
|
||||||
private FixedURLSpan(String url) {
|
private FixedURLSpan(String url) {
|
||||||
super(url);
|
super(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void fix(final Editable editable) {
|
public static void fix(final Editable editable) {
|
||||||
for (final URLSpan urlspan : editable.getSpans(0, editable.length() - 1, URLSpan.class)) {
|
for (final URLSpan urlspan : editable.getSpans(0, editable.length() - 1, URLSpan.class)) {
|
||||||
final int start = editable.getSpanStart(urlspan);
|
final int start = editable.getSpanStart(urlspan);
|
||||||
final int end = editable.getSpanEnd(urlspan);
|
final int end = editable.getSpanEnd(urlspan);
|
||||||
editable.removeSpan(urlspan);
|
editable.removeSpan(urlspan);
|
||||||
editable.setSpan(new FixedURLSpan(urlspan.getURL()), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
editable.setSpan(
|
||||||
}
|
new FixedURLSpan(urlspan.getURL()),
|
||||||
}
|
start,
|
||||||
|
end,
|
||||||
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View widget) {
|
public void onClick(final View widget) {
|
||||||
final Uri uri = Uri.parse(getURL());
|
final Uri uri = Uri.parse(getURL());
|
||||||
final Context context = widget.getContext();
|
final Context context = widget.getContext();
|
||||||
final boolean candidateToProcessDirectly = "xmpp".equals(uri.getScheme()) || ("https".equals(uri.getScheme()) && "conversations.im".equals(uri.getHost()) && uri.getPathSegments().size() > 1 && Arrays.asList("j","i").contains(uri.getPathSegments().get(0)));
|
final boolean candidateToProcessDirectly =
|
||||||
if (candidateToProcessDirectly && context instanceof ConversationsActivity) {
|
"xmpp".equals(uri.getScheme())
|
||||||
if (((ConversationsActivity) context).onXmppUriClicked(uri)) {
|
|| ("https".equals(uri.getScheme())
|
||||||
widget.playSoundEffect(0);
|
&& "conversations.im".equals(uri.getHost())
|
||||||
return;
|
&& uri.getPathSegments().size() > 1
|
||||||
}
|
&& Arrays.asList("j", "i").contains(uri.getPathSegments().get(0)));
|
||||||
}
|
if (candidateToProcessDirectly && context instanceof ConversationsActivity) {
|
||||||
final Intent intent = new Intent(Intent.ACTION_VIEW, uri);
|
if (((ConversationsActivity) context).onXmppUriClicked(uri)) {
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
|
widget.playSoundEffect(SoundEffectConstants.CLICK);
|
||||||
//intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
|
return;
|
||||||
try {
|
}
|
||||||
context.startActivity(intent);
|
}
|
||||||
widget.playSoundEffect(0);
|
final Intent intent = new Intent(Intent.ACTION_VIEW, uri);
|
||||||
} catch (ActivityNotFoundException e) {
|
if ("geo".equalsIgnoreCase(uri.getScheme())) {
|
||||||
Toast.makeText(context, R.string.no_application_found_to_open_link, Toast.LENGTH_SHORT).show();
|
intent.setClass(context, ShowLocationActivity.class);
|
||||||
}
|
} else {
|
||||||
}
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
context.startActivity(intent);
|
||||||
|
widget.playSoundEffect(SoundEffectConstants.CLICK);
|
||||||
|
} catch (ActivityNotFoundException e) {
|
||||||
|
Toast.makeText(context, R.string.no_application_found_to_open_link, Toast.LENGTH_SHORT)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package eu.siacs.conversations.ui.util;
|
package eu.siacs.conversations.ui.util;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper methods for parsing URI's.
|
* Helper methods for parsing URI's.
|
||||||
|
@ -12,19 +14,18 @@ public final class UriHelper {
|
||||||
* @param q The query string to split.
|
* @param q The query string to split.
|
||||||
* @return A hashmap containing the key-value pairs from the query string.
|
* @return A hashmap containing the key-value pairs from the query string.
|
||||||
*/
|
*/
|
||||||
public static HashMap<String, String> parseQueryString(final String q) {
|
public static Map<String, String> parseQueryString(final String q) {
|
||||||
if (q == null || q.isEmpty()) {
|
if (q == null || q.isEmpty()) {
|
||||||
return null;
|
return ImmutableMap.of();
|
||||||
}
|
}
|
||||||
|
final ImmutableMap.Builder<String,String> queryMapBuilder = new ImmutableMap.Builder<>();
|
||||||
|
|
||||||
final String[] query = q.split("&");
|
final String[] query = q.split("&");
|
||||||
// TODO: Look up the HashMap implementation and figure out what the load factor is and make sure we're not reallocating here.
|
|
||||||
final HashMap<String, String> queryMap = new HashMap<>(query.length);
|
|
||||||
for (final String param : query) {
|
for (final String param : query) {
|
||||||
final String[] pair = param.split("=");
|
final String[] pair = param.split("=");
|
||||||
queryMap.put(pair[0], pair.length == 2 && !pair[1].isEmpty() ? pair[1] : null);
|
queryMapBuilder.put(pair[0], pair.length == 2 && !pair[1].isEmpty() ? pair[1] : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return queryMap;
|
return queryMapBuilder.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -46,13 +46,17 @@ public class GeoHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static GeoPoint parseGeoPoint(final Uri uri) {
|
||||||
|
return parseGeoPoint(uri.toString());
|
||||||
|
}
|
||||||
|
|
||||||
private static GeoPoint parseGeoPoint(String body) throws IllegalArgumentException {
|
private static GeoPoint parseGeoPoint(String body) throws IllegalArgumentException {
|
||||||
Matcher matcher = GEO_URI.matcher(body);
|
final Matcher matcher = GEO_URI.matcher(body);
|
||||||
if (!matcher.matches()) {
|
if (!matcher.matches()) {
|
||||||
throw new IllegalArgumentException("Invalid geo uri");
|
throw new IllegalArgumentException("Invalid geo uri");
|
||||||
}
|
}
|
||||||
double latitude;
|
final double latitude;
|
||||||
double longitude;
|
final double longitude;
|
||||||
try {
|
try {
|
||||||
latitude = Double.parseDouble(matcher.group(1));
|
latitude = Double.parseDouble(matcher.group(1));
|
||||||
if (latitude > 90.0 || latitude < -90.0) {
|
if (latitude > 90.0 || latitude < -90.0) {
|
||||||
|
@ -62,7 +66,7 @@ public class GeoHelper {
|
||||||
if (longitude > 180.0 || longitude < -180.0) {
|
if (longitude > 180.0 || longitude < -180.0) {
|
||||||
throw new IllegalArgumentException("Invalid geo uri");
|
throw new IllegalArgumentException("Invalid geo uri");
|
||||||
}
|
}
|
||||||
} catch (NumberFormatException e) {
|
} catch (final NumberFormatException e) {
|
||||||
throw new IllegalArgumentException("Invalid geo uri",e);
|
throw new IllegalArgumentException("Invalid geo uri",e);
|
||||||
}
|
}
|
||||||
return new GeoPoint(latitude, longitude);
|
return new GeoPoint(latitude, longitude);
|
||||||
|
|
|
@ -7,6 +7,6 @@
|
||||||
|
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z" />
|
android:pathData="M10,9h4L14,6h3l-5,-5 -5,5h3v3zM9,10L6,10L6,7l-5,5 5,5v-3h3v-4zM23,12l-5,-5v3h-3v4h3v3l5,-5zM14,15h-4v3L7,18l5,5 5,-5h-3v-3z" />
|
||||||
|
|
||||||
</vector>
|
</vector>
|
|
@ -6,9 +6,13 @@
|
||||||
android:showAsAction="ifRoom"
|
android:showAsAction="ifRoom"
|
||||||
android:title="@string/action_share_location"
|
android:title="@string/action_share_location"
|
||||||
android:icon="@drawable/ic_share_24dp"/>
|
android:icon="@drawable/ic_share_24dp"/>
|
||||||
|
<item android:id="@+id/action_open_with"
|
||||||
|
app:showAsAction="ifRoom"
|
||||||
|
android:showAsAction="ifRoom"
|
||||||
|
android:title="@string/open_with"
|
||||||
|
android:icon="@drawable/ic_open_with_24dp"/>
|
||||||
<item android:id="@+id/action_copy_location"
|
<item android:id="@+id/action_copy_location"
|
||||||
android:title="@string/action_copy_location"
|
android:title="@string/action_copy_location"
|
||||||
android:icon="@drawable/ic_content_copy_24dp"
|
app:showAsAction="never"
|
||||||
app:showAsAction="ifRoom"
|
|
||||||
android:showAsAction="ifRoom"/>
|
android:showAsAction="ifRoom"/>
|
||||||
</menu>
|
</menu>
|
Loading…
Reference in a new issue