Commit 301eb0d0 authored by Bartek Fabiszewski's avatar Bartek Fabiszewski
Browse files

Rewrite LoggerTask to better handle getCurrentLocation (API 30+)

parent b0b9a943
Loading
Loading
Loading
Loading
+17 −13
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@ import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Build;
import android.os.Handler;
import android.os.CancellationSignal;
import android.os.Looper;
import android.os.SystemClock;
import android.util.Log;
@@ -96,7 +96,6 @@ class LocationHelper {
    /**
     * Check if user granted permission to access location.
     *
     * @param context Context
     * @return True if permission granted, false otherwise
     */
    boolean canAccessLocation() {
@@ -119,11 +118,11 @@ class LocationHelper {
    /**
     * Request single location update
     * @param listener Listener
     * @param looper Looper
     * @param cancellationSignal Cancellation signal
     * @throws LoggerException Exception on permission denied or all providers disabled
     */
    void requestSingleUpdate(@NonNull LocationListener listener, @Nullable Looper looper) throws LoggerException {
        requestAllProvidersUpdates(listener, looper, true);
    void requestSingleUpdate(@NonNull LocationListener listener, CancellationSignal cancellationSignal) throws LoggerException {
        requestAllProvidersUpdates(listener, Looper.getMainLooper(), true, cancellationSignal);
    }

    /**
@@ -133,7 +132,7 @@ class LocationHelper {
     * @throws LoggerException Exception on all requested providers failure
     */
    void requestLocationUpdates(@NonNull LocationListener listener, @Nullable Looper looper) throws LoggerException {
        requestAllProvidersUpdates(listener, looper, false);
        requestAllProvidersUpdates(listener, looper, false, null);
    }

    /**
@@ -141,13 +140,15 @@ class LocationHelper {
     * @param listener Listener
     * @param looper Looper
     * @param singleShot Request single update if true
     * @param cancellationSignal Cancellation signal
     * @throws LoggerException Exception on all requested providers failure
     */
    private void requestAllProvidersUpdates(@NonNull LocationListener listener, @Nullable Looper looper, boolean singleShot) throws LoggerException {
    private void requestAllProvidersUpdates(@NonNull LocationListener listener, @Nullable Looper looper, 
                                            boolean singleShot, CancellationSignal cancellationSignal) throws LoggerException {
        List<Integer> results = new ArrayList<>();
        for (String provider : userProviders) {
            try {
                requestProviderUpdates(provider, listener, looper, singleShot);
                requestProviderUpdates(provider, listener, looper, singleShot, cancellationSignal);
                results.add(LoggerException.E_OK);
            } catch (LoggerException e) {
                results.add(e.getCode());
@@ -165,10 +166,12 @@ class LocationHelper {
     * @param listener Listener
     * @param looper Looper
     * @param singleShot Request single update if true
     * @param cancellationSignal Cancellation signal
     * @throws LoggerException Exception on permission denied or provider disabled
     */
    @SuppressWarnings({"deprecation", "RedundantSuppression"})
    private void requestProviderUpdates(@NonNull String provider, @NonNull LocationListener listener, @Nullable Looper looper, boolean singleShot) throws LoggerException {
    private void requestProviderUpdates(@NonNull String provider, @NonNull LocationListener listener, @Nullable Looper looper,
                                        boolean singleShot, @Nullable CancellationSignal cancellationSignal) throws LoggerException {
        if (Logger.DEBUG) { Log.d(TAG, "[requestProviderUpdates: " + provider + " (" + singleShot + ")]"); }
        try {
            if (!singleShot) {
@@ -176,11 +179,12 @@ class LocationHelper {
                locationManager.requestLocationUpdates(provider, minTimeMillis, minDistance, listener, looper);
            } else if (locationManager.isProviderEnabled(provider)) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                    locationManager.getCurrentLocation(provider, null, runnable -> {
                        if (looper != null) {
                            new Handler(looper).post(runnable);
                    locationManager.getCurrentLocation(provider, cancellationSignal, context.getMainExecutor(), location -> {
                        if (Logger.DEBUG) { Log.d(TAG, "[getCurrentLocation location: " + location + ", provider: " + provider + "]"); }
                        if (location != null) {
                            listener.onLocationChanged(location);
                        }
                    }, listener::onLocationChanged);
                    });
                } else {
                    locationManager.requestSingleUpdate(provider, listener, looper);
                }
+24 −5
Original line number Diff line number Diff line
@@ -12,7 +12,9 @@ package net.fabiszewski.ulogger;
import android.app.Activity;
import android.location.Location;
import android.location.LocationListener;
import android.os.Build;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
@@ -43,6 +45,8 @@ class LoggerTask implements LocationListener, Runnable {
    private boolean isCancelled = false;
    private boolean isRunning = false;

    private CancellationSignal cancellationSignal = null;

    private final Handler uiHandler = new Handler(Looper.getMainLooper());
    private final Object lock = new Object();

@@ -55,6 +59,7 @@ class LoggerTask implements LocationListener, Runnable {

    @Override
    public void run() {
        if (Logger.DEBUG) { Log.d(TAG, "[task run]"); }
        isRunning = true;
        Location location = doInBackground();
        if (!isCancelled) {
@@ -92,7 +97,10 @@ class LoggerTask implements LocationListener, Runnable {
            waiting = true;
            final long startTime = System.currentTimeMillis();
            try {
                locationHelper.requestSingleUpdate(this, Looper.getMainLooper());
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                    cancellationSignal = new CancellationSignal();
                }
                locationHelper.requestSingleUpdate(this, cancellationSignal);
                while (waiting) {
                    try {
                        lock.wait(TIMEOUT_MS);
@@ -104,7 +112,7 @@ class LoggerTask implements LocationListener, Runnable {
                        waiting = false;
                    }
                }
                locationHelper.removeUpdates(this);
                removeUpdates();
                return location;
            } catch (LocationHelper.LoggerException e) {
                error = e.getCode();
@@ -113,6 +121,17 @@ class LoggerTask implements LocationListener, Runnable {
        return null;
    }

    /**
     * Remove updates
     * Uses locationManager or cancellation signal if supported
     */
    private void removeUpdates() {
        locationHelper.removeUpdates(this);
        if (cancellationSignal != null) {
            cancellationSignal.cancel();
        }
    }

    /**
     * Quit loop
     */
@@ -156,8 +175,8 @@ class LoggerTask implements LocationListener, Runnable {
    private void restartUpdates() throws LocationHelper.LoggerException {
        if (Logger.DEBUG) { Log.d(TAG, "[location updates restart]"); }

        locationHelper.removeUpdates(this);
        locationHelper.requestSingleUpdate(this, Looper.getMainLooper());
        removeUpdates();
        locationHelper.requestSingleUpdate(this, cancellationSignal);
    }


@@ -177,7 +196,7 @@ class LoggerTask implements LocationListener, Runnable {
     * @param location Location
     * @return True if skipped
     */
    private boolean hasRequiredAccuracy(Location location) {
    private boolean hasRequiredAccuracy(@NonNull Location location) {

        if (!locationHelper.hasRequiredAccuracy(location)) {
            try {
+8 −3
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
package net.fabiszewski.ulogger;

import android.Manifest;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
@@ -267,7 +268,7 @@ public class WaypointFragment extends Fragment implements LoggerTask.LoggerTaskC
    }

    private void takePhoto() {
        if (!hasPermissions()) {
        if (!hasStoragePermission()) {
            return;
        }
        requestImageCapture();
@@ -284,7 +285,7 @@ public class WaypointFragment extends Fragment implements LoggerTask.LoggerTaskC
        }
    }

    private boolean hasPermissions() {
    private boolean hasStoragePermission() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            showToast("You must accept permission for writing photo to external storage");
@@ -421,6 +422,10 @@ public class WaypointFragment extends Fragment implements LoggerTask.LoggerTaskC
        locationTextView.setText(getString(R.string.logger_task_failure));
        if ((reason & LoggerTask.E_PERMISSION) != 0) {
            showToast(getString(R.string.location_permission_denied));
            Activity activity = getActivity();
            if (activity != null) {
                ActivityCompat.requestPermissions(activity, new String[]{ Manifest.permission.ACCESS_FINE_LOCATION }, PERMISSION_LOCATION);
            }
        }
        if ((reason & LoggerTask.E_DISABLED) != 0) {
            showToast(getString(R.string.location_disabled));