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