1package eu.siacs.conversations.ui;
2
3import android.Manifest;
4import android.content.Intent;
5import android.content.pm.PackageManager;
6import androidx.databinding.DataBindingUtil;
7import android.location.Location;
8import android.location.LocationListener;
9import android.os.Build;
10import android.os.Bundle;
11import androidx.annotation.NonNull;
12import com.google.android.material.snackbar.Snackbar;
13import androidx.appcompat.widget.Toolbar;
14import android.view.View;
15
16import org.osmdroid.api.IGeoPoint;
17import org.osmdroid.util.GeoPoint;
18
19import eu.siacs.conversations.Config;
20import eu.siacs.conversations.R;
21import eu.siacs.conversations.databinding.ActivityShareLocationBinding;
22import eu.siacs.conversations.ui.util.LocationHelper;
23import eu.siacs.conversations.ui.widget.Marker;
24import eu.siacs.conversations.ui.widget.MyLocation;
25import eu.siacs.conversations.utils.LocationProvider;
26import eu.siacs.conversations.utils.ThemeHelper;
27
28public class ShareLocationActivity extends LocationActivity implements LocationListener {
29
30 private Snackbar snackBar;
31 private ActivityShareLocationBinding binding;
32 private boolean marker_fixed_to_loc = false;
33 private static final String KEY_FIXED_TO_LOC = "fixed_to_loc";
34 private Boolean noAskAgain = false;
35
36 @Override
37 protected void onSaveInstanceState(@NonNull final Bundle outState) {
38 super.onSaveInstanceState(outState);
39
40 outState.putBoolean(KEY_FIXED_TO_LOC, marker_fixed_to_loc);
41 }
42
43 @Override
44 protected void onRestoreInstanceState(@NonNull final Bundle savedInstanceState) {
45 super.onRestoreInstanceState(savedInstanceState);
46
47 if (savedInstanceState.containsKey(KEY_FIXED_TO_LOC)) {
48 this.marker_fixed_to_loc = savedInstanceState.getBoolean(KEY_FIXED_TO_LOC);
49 }
50 }
51
52 @Override
53 protected void onCreate(final Bundle savedInstanceState) {
54 super.onCreate(savedInstanceState);
55
56 this.binding = DataBindingUtil.setContentView(this,R.layout.activity_share_location);
57 setSupportActionBar((Toolbar) binding.toolbar);
58 configureActionBar(getSupportActionBar());
59 setupMapView(binding.map, LocationProvider.getGeoPoint(this));
60
61 this.binding.cancelButton.setOnClickListener(view -> {
62 setResult(RESULT_CANCELED);
63 finish();
64 });
65
66 this.snackBar = Snackbar.make(this.binding.snackbarCoordinator, R.string.location_disabled, Snackbar.LENGTH_INDEFINITE);
67 this.snackBar.setAction(R.string.enable, view -> {
68 if (isLocationEnabledAndAllowed()) {
69 updateUi();
70 } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !hasLocationPermissions()) {
71 requestPermissions(REQUEST_CODE_SNACKBAR_PRESSED);
72 } else if (!isLocationEnabled()) {
73 startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
74 }
75 });
76 ThemeHelper.fix(this.snackBar);
77
78 this.binding.shareButton.setOnClickListener(view -> {
79 final Intent result = new Intent();
80
81 if (marker_fixed_to_loc && myLoc != null) {
82 result.putExtra("latitude", myLoc.getLatitude());
83 result.putExtra("longitude", myLoc.getLongitude());
84 result.putExtra("altitude", myLoc.getAltitude());
85 result.putExtra("accuracy", (int) myLoc.getAccuracy());
86 } else {
87 final IGeoPoint markerPoint = this.binding.map.getMapCenter();
88 result.putExtra("latitude", markerPoint.getLatitude());
89 result.putExtra("longitude", markerPoint.getLongitude());
90 }
91
92 setResult(RESULT_OK, result);
93 finish();
94 });
95
96 this.marker_fixed_to_loc = isLocationEnabledAndAllowed();
97
98 this.binding.fab.setOnClickListener(view -> {
99 if (!marker_fixed_to_loc) {
100 if (!isLocationEnabled()) {
101 startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
102 } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
103 requestPermissions(REQUEST_CODE_FAB_PRESSED);
104 }
105 }
106 toggleFixedLocation();
107 });
108 }
109
110 @Override
111 public void onRequestPermissionsResult(final int requestCode,
112 @NonNull final String[] permissions,
113 @NonNull final int[] grantResults) {
114 super.onRequestPermissionsResult(requestCode, permissions, grantResults);
115
116 if (grantResults.length > 0 &&
117 grantResults[0] != PackageManager.PERMISSION_GRANTED &&
118 Build.VERSION.SDK_INT >= 23 &&
119 permissions.length > 0 &&
120 (
121 Manifest.permission.LOCATION_HARDWARE.equals(permissions[0]) ||
122 Manifest.permission.ACCESS_FINE_LOCATION.equals(permissions[0]) ||
123 Manifest.permission.ACCESS_COARSE_LOCATION.equals(permissions[0])
124 ) &&
125 !shouldShowRequestPermissionRationale(permissions[0])) {
126 noAskAgain = true;
127 }
128
129 if (!noAskAgain && requestCode == REQUEST_CODE_SNACKBAR_PRESSED && !isLocationEnabled() && hasLocationPermissions()) {
130 startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
131 }
132 updateUi();
133 }
134
135 @Override
136 protected void gotoLoc(final boolean setZoomLevel) {
137 if (this.myLoc != null && mapController != null) {
138 if (setZoomLevel) {
139 mapController.setZoom(Config.Map.FINAL_ZOOM_LEVEL);
140 }
141 mapController.animateTo(new GeoPoint(this.myLoc));
142 }
143 }
144
145 @Override
146 protected void setMyLoc(final Location location) {
147 this.myLoc = location;
148 }
149
150 @Override
151 protected void onPause() {
152 super.onPause();
153 }
154
155 @Override
156 protected void updateLocationMarkers() {
157 super.updateLocationMarkers();
158 if (this.myLoc != null) {
159 this.binding.map.getOverlays().add(new MyLocation(this, null, this.myLoc));
160 if (this.marker_fixed_to_loc) {
161 this.binding.map.getOverlays().add(new Marker(marker_icon, new GeoPoint(this.myLoc)));
162 } else {
163 this.binding.map.getOverlays().add(new Marker(marker_icon));
164 }
165 } else {
166 this.binding.map.getOverlays().add(new Marker(marker_icon));
167 }
168 }
169
170 @Override
171 public void onLocationChanged(final Location location) {
172 if (this.myLoc == null) {
173 this.marker_fixed_to_loc = true;
174 }
175 updateUi();
176 if (LocationHelper.isBetterLocation(location, this.myLoc)) {
177 final Location oldLoc = this.myLoc;
178 this.myLoc = location;
179
180 // Don't jump back to the users location if they're not moving (more or less).
181 if (oldLoc == null || (this.marker_fixed_to_loc && this.myLoc.distanceTo(oldLoc) > 1)) {
182 gotoLoc();
183 }
184
185 updateLocationMarkers();
186 }
187 }
188
189 @Override
190 public void onStatusChanged(final String provider, final int status, final Bundle extras) {
191
192 }
193
194 @Override
195 public void onProviderEnabled(final String provider) {
196
197 }
198
199 @Override
200 public void onProviderDisabled(final String provider) {
201
202 }
203
204 private boolean isLocationEnabledAndAllowed() {
205 return this.hasLocationFeature && (Build.VERSION.SDK_INT < Build.VERSION_CODES.M || this.hasLocationPermissions()) && this.isLocationEnabled();
206 }
207
208 private void toggleFixedLocation() {
209 this.marker_fixed_to_loc = isLocationEnabledAndAllowed() && !this.marker_fixed_to_loc;
210 if (this.marker_fixed_to_loc) {
211 gotoLoc(false);
212 }
213 updateLocationMarkers();
214 updateUi();
215 }
216
217 @Override
218 protected void updateUi() {
219 if (!hasLocationFeature || noAskAgain || isLocationEnabledAndAllowed()) {
220 this.snackBar.dismiss();
221 } else {
222 this.snackBar.show();
223 }
224
225 if (isLocationEnabledAndAllowed()) {
226 this.binding.fab.setVisibility(View.VISIBLE);
227 runOnUiThread(() -> {
228 this.binding.fab.setImageResource(marker_fixed_to_loc ? R.drawable.ic_gps_fixed_white_24dp :
229 R.drawable.ic_gps_not_fixed_white_24dp);
230 this.binding.fab.setContentDescription(getResources().getString(
231 marker_fixed_to_loc ? R.string.action_unfix_from_location : R.string.action_fix_to_location
232 ));
233 this.binding.fab.invalidate();
234 });
235 } else {
236 this.binding.fab.setVisibility(View.GONE);
237 }
238 }
239}