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}