GeoHelper.java

  1package eu.siacs.conversations.utils;
  2
  3import android.content.Context;
  4import android.content.Intent;
  5import android.content.SharedPreferences;
  6import android.net.Uri;
  7import android.preference.PreferenceManager;
  8import eu.siacs.conversations.R;
  9import eu.siacs.conversations.entities.Contact;
 10import eu.siacs.conversations.entities.Conversational;
 11import eu.siacs.conversations.entities.Message;
 12import eu.siacs.conversations.ui.ShareLocationActivity;
 13import eu.siacs.conversations.ui.ShowLocationActivity;
 14import java.io.UnsupportedEncodingException;
 15import java.net.URLEncoder;
 16import java.util.ArrayList;
 17import java.util.regex.Matcher;
 18import org.osmdroid.util.GeoPoint;
 19
 20public class GeoHelper {
 21
 22    private static final String SHARE_LOCATION_PACKAGE_NAME =
 23            "eu.siacs.conversations.location.request";
 24    private static final String SHOW_LOCATION_PACKAGE_NAME = "eu.siacs.conversations.location.show";
 25
 26    public static boolean isLocationPluginInstalled(Context context) {
 27        return new Intent(SHARE_LOCATION_PACKAGE_NAME).resolveActivity(context.getPackageManager())
 28                != null;
 29    }
 30
 31    public static boolean isLocationPluginInstalledAndDesired(Context context) {
 32        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
 33        final boolean configured =
 34                preferences.getBoolean(
 35                        "use_share_location_plugin",
 36                        context.getResources().getBoolean(R.bool.use_share_location_plugin));
 37        return configured && isLocationPluginInstalled(context);
 38    }
 39
 40    public static Intent getFetchIntent(Context context) {
 41        if (isLocationPluginInstalledAndDesired(context)) {
 42            return new Intent(SHARE_LOCATION_PACKAGE_NAME);
 43        } else {
 44            return new Intent(context, ShareLocationActivity.class);
 45        }
 46    }
 47
 48    public static GeoPoint parseGeoPoint(final Uri uri) {
 49        return parseGeoPoint(uri.toString());
 50    }
 51
 52    private static GeoPoint parseGeoPoint(String body) throws IllegalArgumentException {
 53        final Matcher matcher = Patterns.URI_GEO.matcher(body);
 54        if (!matcher.matches()) {
 55            throw new IllegalArgumentException("Invalid geo uri");
 56        }
 57        final double latitude;
 58        final double longitude;
 59        try {
 60            latitude = Double.parseDouble(matcher.group(1));
 61            if (latitude > 90.0 || latitude < -90.0) {
 62                throw new IllegalArgumentException("Invalid geo uri");
 63            }
 64            longitude = Double.parseDouble(matcher.group(2));
 65            if (longitude > 180.0 || longitude < -180.0) {
 66                throw new IllegalArgumentException("Invalid geo uri");
 67            }
 68        } catch (final NumberFormatException e) {
 69            throw new IllegalArgumentException("Invalid geo uri", e);
 70        }
 71        return new GeoPoint(latitude, longitude);
 72    }
 73
 74    public static ArrayList<Intent> createGeoIntentsFromMessage(Context context, Message message) {
 75        final ArrayList<Intent> intents = new ArrayList<>();
 76        final GeoPoint geoPoint;
 77        try {
 78            geoPoint = parseGeoPoint(message.getBody());
 79        } catch (IllegalArgumentException e) {
 80            return intents;
 81        }
 82        final Conversational conversation = message.getConversation();
 83        final String label = getLabel(context, message);
 84
 85        if (isLocationPluginInstalledAndDesired(context)) {
 86            Intent locationPluginIntent = new Intent(SHOW_LOCATION_PACKAGE_NAME);
 87            locationPluginIntent.putExtra("latitude", geoPoint.getLatitude());
 88            locationPluginIntent.putExtra("longitude", geoPoint.getLongitude());
 89            if (message.getStatus() != Message.STATUS_RECEIVED) {
 90                locationPluginIntent.putExtra("jid", conversation.getAccount().getJid().toString());
 91                locationPluginIntent.putExtra(
 92                        "name", conversation.getAccount().getJid().getLocal());
 93            } else {
 94                Contact contact = message.getContact();
 95                if (contact != null) {
 96                    locationPluginIntent.putExtra("name", contact.getDisplayName());
 97                    locationPluginIntent.putExtra("jid", contact.getJid().toString());
 98                } else {
 99                    locationPluginIntent.putExtra(
100                            "name", UIHelper.getDisplayedMucCounterpart(message.getCounterpart()));
101                }
102            }
103            intents.add(locationPluginIntent);
104        } else {
105            Intent intent = new Intent(context, ShowLocationActivity.class);
106            intent.setAction(SHOW_LOCATION_PACKAGE_NAME);
107            intent.putExtra("latitude", geoPoint.getLatitude());
108            intent.putExtra("longitude", geoPoint.getLongitude());
109            intents.add(intent);
110        }
111
112        intents.add(geoIntent(geoPoint, label));
113
114        Intent httpIntent = new Intent(Intent.ACTION_VIEW);
115        httpIntent.setData(
116                Uri.parse(
117                        "https://maps.google.com/maps?q=loc:"
118                                + geoPoint.getLatitude()
119                                + ","
120                                + geoPoint.getLongitude()
121                                + label));
122        intents.add(httpIntent);
123        return intents;
124    }
125
126    public static void view(Context context, Message message) {
127        final GeoPoint geoPoint = parseGeoPoint(message.getBody());
128        final String label = getLabel(context, message);
129        context.startActivity(geoIntent(geoPoint, label));
130    }
131
132    private static Intent geoIntent(GeoPoint geoPoint, String label) {
133        Intent geoIntent = new Intent(Intent.ACTION_VIEW);
134        geoIntent.setData(
135                Uri.parse(
136                        "geo:"
137                                + geoPoint.getLatitude()
138                                + ","
139                                + geoPoint.getLongitude()
140                                + "?q="
141                                + geoPoint.getLatitude()
142                                + ","
143                                + geoPoint.getLongitude()
144                                + "("
145                                + label
146                                + ")"));
147        return geoIntent;
148    }
149
150    public static boolean openInOsmAnd(Context context, Message message) {
151        try {
152            final GeoPoint geoPoint = parseGeoPoint(message.getBody());
153            final String label = getLabel(context, message);
154            return geoIntent(geoPoint, label).resolveActivity(context.getPackageManager()) != null;
155        } catch (IllegalArgumentException e) {
156            return false;
157        }
158    }
159
160    private static String getLabel(Context context, Message message) {
161        if (message.getStatus() == Message.STATUS_RECEIVED) {
162            try {
163                return URLEncoder.encode(UIHelper.getMessageDisplayName(message), "UTF-8");
164            } catch (UnsupportedEncodingException e) {
165                throw new AssertionError(e);
166            }
167        } else {
168            return context.getString(R.string.me);
169        }
170    }
171}