1package eu.siacs.conversations.ui;
2
3import android.content.ActivityNotFoundException;
4import android.content.ClipData;
5import android.content.ClipboardManager;
6import android.content.ComponentName;
7import android.content.Intent;
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
35
36public class ShowLocationActivity extends LocationActivity implements LocationListener {
37
38 private GeoPoint loc = LocationProvider.FALLBACK;
39 private ActivityShowLocationBinding binding;
40
41
42 private Uri createGeoUri() {
43 return Uri.parse("geo:" + this.loc.getLatitude() + "," + this.loc.getLongitude());
44 }
45
46 @Override
47 protected void onCreate(final Bundle savedInstanceState) {
48 super.onCreate(savedInstanceState);
49
50 this.binding = DataBindingUtil.setContentView(this,R.layout.activity_show_location);
51 setSupportActionBar(binding.toolbar);
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 = 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 = Pattern.compile("/^([-+]?[0-9]+(\\.[0-9]+)?),([-+]?[0-9]+(\\.[0-9]+)?)(\\(.*\\))?/");
93 final Matcher m = latlng.matcher(q);
94 if (m.matches()) {
95 try {
96 this.loc = new GeoPoint(Double.valueOf(m.group(1)), Double.valueOf(m.group(3)));
97 posInQuery = true;
98 } catch (final Exception ignored) {
99 }
100 }
101 }
102
103 final String schemeSpecificPart = geoUri.getSchemeSpecificPart();
104 if (schemeSpecificPart != null && !schemeSpecificPart.isEmpty()) {
105 try {
106 final GeoPoint latlong = LocationHelper.parseLatLong(schemeSpecificPart);
107 if (latlong != null && !posInQuery) {
108 this.loc = latlong;
109 }
110 } catch (final NumberFormatException ignored) {
111 }
112 }
113 }
114
115 break;
116 }
117 updateLocationMarkers();
118 }
119 }
120
121 @Override
122 protected void gotoLoc(final boolean setZoomLevel) {
123 if (this.loc != null && mapController != null) {
124 if (setZoomLevel) {
125 mapController.setZoom(Config.Map.FINAL_ZOOM_LEVEL);
126 }
127 mapController.animateTo(new GeoPoint(this.loc));
128 }
129 }
130
131 @Override
132 public void onRequestPermissionsResult(final int requestCode,
133 @NonNull final String[] permissions,
134 @NonNull final int[] grantResults) {
135 super.onRequestPermissionsResult(requestCode, permissions, grantResults);
136 updateUi();
137 }
138
139 @Override
140 protected void setMyLoc(final Location location) {
141 this.myLoc = location;
142 }
143
144 @Override
145 public boolean onCreateOptionsMenu(final Menu menu) {
146 // Inflate the menu; this adds items to the action bar if it is present.
147 getMenuInflater().inflate(R.menu.menu_show_location, menu);
148 updateUi();
149 return true;
150 }
151
152 @Override
153 protected void updateLocationMarkers() {
154 super.updateLocationMarkers();
155 if (this.myLoc != null) {
156 this.binding.map.getOverlays().add(new MyLocation(this, null, this.myLoc));
157 }
158 this.binding.map.getOverlays().add(new Marker(this.marker_icon, this.loc));
159 }
160
161 @Override
162 protected void onPause() {
163 super.onPause();
164 }
165
166 @Override
167 public boolean onOptionsItemSelected(final MenuItem item) {
168 switch (item.getItemId()) {
169 case R.id.action_copy_location:
170 final ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
171 if (clipboard != null) {
172 final ClipData clip = ClipData.newPlainText("location", createGeoUri().toString());
173 clipboard.setPrimaryClip(clip);
174 Toast.makeText(this,R.string.url_copied_to_clipboard,Toast.LENGTH_SHORT).show();
175 }
176 return true;
177 case R.id.action_share_location:
178 final Intent shareIntent = new Intent();
179 shareIntent.setAction(Intent.ACTION_SEND);
180 shareIntent.putExtra(Intent.EXTRA_TEXT, createGeoUri().toString());
181 shareIntent.setType("text/plain");
182 try {
183 startActivity(Intent.createChooser(shareIntent, getText(R.string.share_with)));
184 } catch (final ActivityNotFoundException e) {
185 //This should happen only on faulty androids because normally chooser is always available
186 Toast.makeText(this, R.string.no_application_found_to_open_file, Toast.LENGTH_SHORT).show();
187 }
188 return true;
189 }
190 return super.onOptionsItemSelected(item);
191 }
192
193 private void startNavigation() {
194 startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(
195 "google.navigation:q=" +
196 this.loc.getLatitude() + "," + this.loc.getLongitude()
197 )));
198 }
199
200 @Override
201 protected void updateUi() {
202 final Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse("google.navigation:q=0,0"));
203 final ComponentName component = i.resolveActivity(getPackageManager());
204 this.binding.fab.setVisibility(component == null ? View.GONE : View.VISIBLE);
205 }
206
207 @Override
208 public void onLocationChanged(final Location location) {
209 if (LocationHelper.isBetterLocation(location, this.myLoc)) {
210 this.myLoc = location;
211 updateLocationMarkers();
212 }
213 }
214
215 @Override
216 public void onStatusChanged(final String provider, final int status, final Bundle extras) {
217
218 }
219
220 @Override
221 public void onProviderEnabled(final String provider) {
222
223 }
224
225 @Override
226 public void onProviderDisabled(final String provider) {
227
228 }
229}