GPS is now optional: request GPS access in TrackRecordingActivity.

Fixes #1061.
This commit is contained in:
Dennis Guse
2022-01-31 19:06:37 +01:00
parent 8001c03a74
commit 5c06c7548f
4 changed files with 60 additions and 37 deletions
@@ -16,13 +16,11 @@
package de.dennisguse.opentracks; package de.dennisguse.opentracks;
import android.Manifest;
import android.app.ActivityOptions; import android.app.ActivityOptions;
import android.app.SearchManager; import android.app.SearchManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.pm.PackageManager;
import android.database.Cursor; import android.database.Cursor;
import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.AnimatedVectorDrawable;
import android.location.LocationManager; import android.location.LocationManager;
@@ -33,15 +31,11 @@ import android.view.KeyEvent;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.widget.SearchView; import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.cursoradapter.widget.ResourceCursorAdapter; import androidx.cursoradapter.widget.ResourceCursorAdapter;
import androidx.loader.app.LoaderManager; import androidx.loader.app.LoaderManager;
import androidx.loader.content.CursorLoader; import androidx.loader.content.CursorLoader;
@@ -213,8 +207,6 @@ public class TrackListActivity extends AbstractTrackDeleteActivity implements Co
ActivityUtils.configureListViewContextualMenu(viewBinding.trackList, contextualActionModeCallback); ActivityUtils.configureListViewContextualMenu(viewBinding.trackList, contextualActionModeCallback);
loadData(getIntent()); loadData(getIntent());
requestGPSPermissions();
} }
@Override @Override
@@ -392,26 +384,6 @@ public class TrackListActivity extends AbstractTrackDeleteActivity implements Co
return recordingStatus.getTrackId(); return recordingStatus.getTrackId();
} }
private void requestGPSPermissions() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
return;
}
ActivityResultLauncher<String[]> locationPermissionRequest = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), result -> {
Boolean fineLocationGranted = result.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false);
Boolean coarseLocationGranted = result.getOrDefault(Manifest.permission.ACCESS_COARSE_LOCATION, false);
if (fineLocationGranted == null || !fineLocationGranted
|| coarseLocationGranted == null || !coarseLocationGranted) {
Toast.makeText(this, R.string.permission_gps_failed, Toast.LENGTH_SHORT).show();
finish();
}
}
);
String[] permissions = new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION};
locationPermissionRequest.launch(permissions);
}
/** /**
* Updates the menu items with the icon specified. * Updates the menu items with the icon specified.
* *
@@ -1,5 +1,6 @@
package de.dennisguse.opentracks; package de.dennisguse.opentracks;
import android.Manifest;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@@ -11,7 +12,10 @@ import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
@@ -39,6 +43,7 @@ import de.dennisguse.opentracks.ui.markers.MarkerEditActivity;
import de.dennisguse.opentracks.ui.markers.MarkerListActivity; import de.dennisguse.opentracks.ui.markers.MarkerListActivity;
import de.dennisguse.opentracks.util.IntentDashboardUtils; import de.dennisguse.opentracks.util.IntentDashboardUtils;
import de.dennisguse.opentracks.util.IntentUtils; import de.dennisguse.opentracks.util.IntentUtils;
import de.dennisguse.opentracks.util.PermissionUtils;
import de.dennisguse.opentracks.util.TrackIconUtils; import de.dennisguse.opentracks.util.TrackIconUtils;
import de.dennisguse.opentracks.util.TrackUtils; import de.dennisguse.opentracks.util.TrackUtils;
@@ -142,6 +147,8 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
if (savedInstanceState != null) { if (savedInstanceState != null) {
viewBinding.trackDetailActivityViewPager.setCurrentItem(savedInstanceState.getInt(CURRENT_TAB_TAG_KEY)); viewBinding.trackDetailActivityViewPager.setCurrentItem(savedInstanceState.getInt(CURRENT_TAB_TAG_KEY));
} }
requestGPSPermissions();
} }
@Override @Override
@@ -400,4 +407,22 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
setLockscreenPolicy(); setLockscreenPolicy();
setScreenOnPolicy(); setScreenOnPolicy();
} }
private void requestGPSPermissions() {
if (PermissionUtils.hasGPSPermission(this)) {
return;
}
ActivityResultLauncher<String[]> locationPermissionRequest = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), result -> {
Boolean fineLocationGranted = result.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false);
Boolean coarseLocationGranted = result.getOrDefault(Manifest.permission.ACCESS_COARSE_LOCATION, false);
if (fineLocationGranted == null || !fineLocationGranted
|| coarseLocationGranted == null || !coarseLocationGranted) {
Toast.makeText(this, R.string.permission_gps_failed, Toast.LENGTH_SHORT).show();
}
}
);
String[] permissions = new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION};
locationPermissionRequest.launch(permissions);
}
} }
@@ -18,14 +18,16 @@ import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.settings.PreferencesUtils; import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.util.LocationUtils; import de.dennisguse.opentracks.util.LocationUtils;
import de.dennisguse.opentracks.util.PermissionUtils;
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
public class GPSHandler implements LocationListener, GpsStatus.GpsStatusListener, SharedPreferences.OnSharedPreferenceChangeListener { public class GPSHandler implements LocationListener, GpsStatus.GpsStatusListener, SharedPreferences.OnSharedPreferenceChangeListener {
private final String TAG = GPSHandler.class.getSimpleName(); private final String TAG = GPSHandler.class.getSimpleName();
private LocationManager locationManager;
private final TrackPointCreator trackPointCreator; private final TrackPointCreator trackPointCreator;
private Context context;
private LocationManager locationManager;
private GpsStatus gpsStatus; private GpsStatus gpsStatus;
private Duration gpsInterval; private Duration gpsInterval;
private Distance thresholdHorizontalAccuracy; private Distance thresholdHorizontalAccuracy;
@@ -36,6 +38,7 @@ public class GPSHandler implements LocationListener, GpsStatus.GpsStatusListener
} }
public void onStart(@NonNull Context context) { public void onStart(@NonNull Context context) {
this.context = context;
PreferencesUtils.registerOnSharedPreferenceChangeListener(this); PreferencesUtils.registerOnSharedPreferenceChangeListener(this);
gpsStatus = new GpsStatus(context, this); gpsStatus = new GpsStatus(context, this);
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
@@ -51,9 +54,12 @@ public class GPSHandler implements LocationListener, GpsStatus.GpsStatusListener
//TODO upgrade to AGP7.0.0/API31 started complaining about removeUpdates. //TODO upgrade to AGP7.0.0/API31 started complaining about removeUpdates.
public void onStop() { public void onStop() {
lastTrackPoint = null; lastTrackPoint = null;
if (locationManager != null) { if (locationManager != null && context != null) {
locationManager.removeUpdates(this); if (PermissionUtils.hasGPSPermission(context)) {
locationManager.removeUpdates(this);
}
locationManager = null; locationManager = null;
context = null;
} }
if (gpsStatus != null) { if (gpsStatus != null) {
@@ -146,14 +152,16 @@ public class GPSHandler implements LocationListener, GpsStatus.GpsStatusListener
} }
private void registerLocationListener() { private void registerLocationListener() {
if (locationManager == null) { if (locationManager == null || context == null) {
Log.e(TAG, "locationManager is null."); Log.e(TAG, "Not started.");
return; return;
} }
try { if (PermissionUtils.hasGPSPermission(context)) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, gpsInterval.toMillis(), 0, this); try {
} catch (SecurityException e) { locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, gpsInterval.toMillis(), 0, this);
Log.e(TAG, "Could not register location listener; permissions not granted.", e); } catch (SecurityException e) {
Log.e(TAG, "Could not register location listener; permissions not granted.", e);
}
} }
} }
@@ -0,0 +1,18 @@
package de.dennisguse.opentracks.util;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import androidx.core.content.ContextCompat;
public class PermissionUtils {
private PermissionUtils() {
}
public static boolean hasGPSPermission(Context context) {
return ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
}
}