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