ShowLocationActivity.java

  1package eu.siacs.conversations.ui;
  2
  3import android.content.ActivityNotFoundException;
  4import android.content.ClipData;
  5import android.content.ClipboardManager;
  6import android.content.Intent;
  7import android.content.pm.ActivityInfo;
  8import android.location.Location;
  9import android.location.LocationListener;
 10import android.net.Uri;
 11import android.os.Bundle;
 12import android.view.Menu;
 13import android.view.MenuItem;
 14import android.view.View;
 15import android.widget.Toast;
 16
 17import androidx.annotation.NonNull;
 18import androidx.databinding.DataBindingUtil;
 19
 20import org.jetbrains.annotations.NotNull;
 21import org.osmdroid.util.GeoPoint;
 22
 23import java.util.HashMap;
 24import java.util.regex.Matcher;
 25import java.util.regex.Pattern;
 26
 27import eu.siacs.conversations.Config;
 28import eu.siacs.conversations.R;
 29import eu.siacs.conversations.databinding.ActivityShowLocationBinding;
 30import eu.siacs.conversations.ui.util.LocationHelper;
 31import eu.siacs.conversations.ui.util.UriHelper;
 32import eu.siacs.conversations.ui.widget.Marker;
 33import eu.siacs.conversations.ui.widget.MyLocation;
 34import eu.siacs.conversations.utils.LocationProvider;
 35
 36public class ShowLocationActivity extends LocationActivity implements LocationListener {
 37
 38    private GeoPoint loc = LocationProvider.FALLBACK;
 39    private ActivityShowLocationBinding binding;
 40
 41    private Uri createGeoUri() {
 42        return Uri.parse("geo:" + this.loc.getLatitude() + "," + this.loc.getLongitude());
 43    }
 44
 45    @Override
 46    protected void onCreate(final Bundle savedInstanceState) {
 47        super.onCreate(savedInstanceState);
 48
 49        this.binding = DataBindingUtil.setContentView(this, R.layout.activity_show_location);
 50        setSupportActionBar(binding.toolbar);
 51
 52        configureActionBar(getSupportActionBar());
 53        setupMapView(this.binding.map, this.loc);
 54
 55        this.binding.fab.setOnClickListener(view -> startNavigation());
 56
 57        final Intent intent = getIntent();
 58        if (intent != null) {
 59            final String action = intent.getAction();
 60            if (action == null) {
 61                return;
 62            }
 63            switch (action) {
 64                case "eu.siacs.conversations.location.show":
 65                    if (intent.hasExtra("longitude") && intent.hasExtra("latitude")) {
 66                        final double longitude = intent.getDoubleExtra("longitude", 0);
 67                        final double latitude = intent.getDoubleExtra("latitude", 0);
 68                        this.loc = new GeoPoint(latitude, longitude);
 69                    }
 70                    break;
 71                case Intent.ACTION_VIEW:
 72                    final Uri geoUri = intent.getData();
 73
 74                    // Attempt to set zoom level if the geo URI specifies it
 75                    if (geoUri != null) {
 76                        final HashMap<String, String> query =
 77                                UriHelper.parseQueryString(geoUri.getQuery());
 78
 79                        // Check for zoom level.
 80                        final String z = query.get("z");
 81                        if (z != null) {
 82                            try {
 83                                mapController.setZoom(Double.valueOf(z));
 84                            } catch (final Exception ignored) {
 85                            }
 86                        }
 87
 88                        // Check for the actual geo query.
 89                        boolean posInQuery = false;
 90                        final String q = query.get("q");
 91                        if (q != null) {
 92                            final Pattern latlng =
 93                                    Pattern.compile(
 94                                            "/^([-+]?[0-9]+(\\.[0-9]+)?),([-+]?[0-9]+(\\.[0-9]+)?)(\\(.*\\))?/");
 95                            final Matcher m = latlng.matcher(q);
 96                            if (m.matches()) {
 97                                try {
 98                                    this.loc =
 99                                            new GeoPoint(
100                                                    Double.valueOf(m.group(1)),
101                                                    Double.valueOf(m.group(3)));
102                                    posInQuery = true;
103                                } catch (final Exception ignored) {
104                                }
105                            }
106                        }
107
108                        final String schemeSpecificPart = geoUri.getSchemeSpecificPart();
109                        if (schemeSpecificPart != null && !schemeSpecificPart.isEmpty()) {
110                            try {
111                                final GeoPoint latlong =
112                                        LocationHelper.parseLatLong(schemeSpecificPart);
113                                if (latlong != null && !posInQuery) {
114                                    this.loc = latlong;
115                                }
116                            } catch (final NumberFormatException ignored) {
117                            }
118                        }
119                    }
120
121                    break;
122            }
123            updateLocationMarkers();
124        }
125    }
126
127    @Override
128    protected void gotoLoc(final boolean setZoomLevel) {
129        if (this.loc != null && mapController != null) {
130            if (setZoomLevel) {
131                mapController.setZoom(Config.Map.FINAL_ZOOM_LEVEL);
132            }
133            mapController.animateTo(new GeoPoint(this.loc));
134        }
135    }
136
137    @Override
138    public void onRequestPermissionsResult(
139            final int requestCode,
140            @NonNull final String[] permissions,
141            @NonNull final int[] grantResults) {
142        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
143        updateUi();
144    }
145
146    @Override
147    protected void setMyLoc(final Location location) {
148        this.myLoc = location;
149    }
150
151    @Override
152    public boolean onCreateOptionsMenu(@NotNull final Menu menu) {
153        // Inflate the menu; this adds items to the action bar if it is present.
154        getMenuInflater().inflate(R.menu.menu_show_location, menu);
155        updateUi();
156        return true;
157    }
158
159    @Override
160    protected void updateLocationMarkers() {
161        super.updateLocationMarkers();
162        if (this.myLoc != null) {
163            this.binding.map.getOverlays().add(new MyLocation(this, null, this.myLoc));
164        }
165        this.binding.map.getOverlays().add(new Marker(this.marker_icon, this.loc));
166    }
167
168    @Override
169    protected void onPause() {
170        super.onPause();
171    }
172
173    @Override
174    public boolean onOptionsItemSelected(final MenuItem item) {
175        switch (item.getItemId()) {
176            case R.id.action_copy_location:
177                final ClipboardManager clipboard =
178                        (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
179                if (clipboard != null) {
180                    final ClipData clip =
181                            ClipData.newPlainText("location", createGeoUri().toString());
182                    clipboard.setPrimaryClip(clip);
183                    Toast.makeText(this, R.string.url_copied_to_clipboard, Toast.LENGTH_SHORT)
184                            .show();
185                }
186                return true;
187            case R.id.action_share_location:
188                final Intent shareIntent = new Intent();
189                shareIntent.setAction(Intent.ACTION_SEND);
190                shareIntent.putExtra(Intent.EXTRA_TEXT, createGeoUri().toString());
191                shareIntent.setType("text/plain");
192                try {
193                    startActivity(Intent.createChooser(shareIntent, getText(R.string.share_with)));
194                } catch (final ActivityNotFoundException e) {
195                    // This should happen only on faulty androids because normally chooser is always
196                    // available
197                    Toast.makeText(
198                                    this,
199                                    R.string.no_application_found_to_open_file,
200                                    Toast.LENGTH_SHORT)
201                            .show();
202                }
203                return true;
204        }
205        return super.onOptionsItemSelected(item);
206    }
207
208    private void startNavigation() {
209        final Intent intent = getStartNavigationIntent();
210        startActivity(intent);
211    }
212
213    private Intent getStartNavigationIntent() {
214        return new Intent(
215                Intent.ACTION_VIEW,
216                Uri.parse(
217                        "google.navigation:q="
218                                + this.loc.getLatitude()
219                                + ","
220                                + this.loc.getLongitude()));
221    }
222
223    @Override
224    protected void updateUi() {
225        final Intent intent = getStartNavigationIntent();
226        final ActivityInfo activityInfo = intent.resolveActivityInfo(getPackageManager(), 0);
227        this.binding.fab.setVisibility(activityInfo == null ? View.GONE : View.VISIBLE);
228    }
229
230    @Override
231    public void onLocationChanged(@NotNull final Location location) {
232        if (LocationHelper.isBetterLocation(location, this.myLoc)) {
233            this.myLoc = location;
234            updateLocationMarkers();
235        }
236    }
237
238    @Override
239    public void onStatusChanged(final String provider, final int status, final Bundle extras) {}
240
241    @Override
242    public void onProviderEnabled(@NotNull final String provider) {}
243
244    @Override
245    public void onProviderDisabled(@NotNull final String provider) {}
246}