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