ShareLocationActivity.java

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