Commit e37d9911 authored by Bartek Fabiszewski's avatar Bartek Fabiszewski
Browse files

Remove deprecated AsyncTask

parent 4096ff56
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -13,7 +13,9 @@
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <!-- For writing camera images API <= 28 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="28"
        tools:ignore="ScopedStorage" />
    <!-- For auto start -->
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <!-- For web sync retries -->
+57 −16
Original line number Diff line number Diff line
@@ -13,16 +13,20 @@ import android.app.Activity;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.annotation.WorkerThread;
import androidx.preference.PreferenceManager;

import java.io.IOException;
import java.lang.ref.WeakReference;

import static net.fabiszewski.ulogger.ImageHelper.clearImageCache;
import static net.fabiszewski.ulogger.ImageHelper.getPersistablePermission;
import static net.fabiszewski.ulogger.ImageHelper.getResampledBitmap;
import static net.fabiszewski.ulogger.ImageHelper.getThumbnail;
@@ -32,26 +36,53 @@ import static net.fabiszewski.ulogger.ImageHelper.saveToCache;
/**
 * Task to downsample image
 */
class ImageTask extends AsyncTask<Uri, Void, ImageTask.ImageTaskResult> {
class ImageTask implements Runnable {

    private static final String TAG = ImageTask.class.getSimpleName();

    private final WeakReference<ImageTaskCallback> weakCallback;

    private String errorMessage = "Image resampling failed";
    private String errorMessage = "";
    private final Uri uri;

    ImageTask(ImageTaskCallback callback) {
    private boolean isRunning = false;
    private boolean isCancelled = false;

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

    ImageTask(Uri uri, ImageTaskCallback callback) {
        this.uri = uri;
        weakCallback = new WeakReference<>(callback);
    }

    @Override
    protected ImageTaskResult doInBackground(Uri... params) {
    public void run() {
        isRunning = true;
        ImageTaskResult result = doInBackground();
        if (isCancelled) {
            cleanUp(result);
        } else {
            uiHandler.post(() -> onPostExecute(result));
        }
        isRunning = false;
    }

    public void cancel() {
        if (Logger.DEBUG) { Log.d(TAG, "[task cancelled]"); }
        isCancelled = true;
    }

    public boolean isRunning() {
        return isRunning;
    }

    @WorkerThread
    private ImageTaskResult doInBackground() {
        if (Logger.DEBUG) { Log.d(TAG, "[doInBackground]"); }
        Activity activity = getActivity();
        if (activity == null || params.length != 1 || params[0] == null) {
        if (activity == null) {
            return null;
        }
        Uri inUri = params[0];
        ImageTaskResult result = null;
        try {
            Uri savedUri;
@@ -60,11 +91,11 @@ class ImageTask extends AsyncTask<Uri, Void, ImageTask.ImageTaskResult> {
            SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
            int dstWidth = Integer.parseInt(prefs.getString(SettingsActivity.KEY_IMAGE_SIZE, activity.getString(R.string.pref_imagesize_default)));
            if (dstWidth == 0) {
                savedUri = inUri;
                getPersistablePermission(activity, inUri);
                thumbnail = getThumbnail(activity, inUri);
                savedUri = uri;
                getPersistablePermission(activity, uri);
                thumbnail = getThumbnail(activity, uri);
            } else {
                Bitmap bitmap = getResampledBitmap(activity, inUri, dstWidth);
                Bitmap bitmap = getResampledBitmap(activity, uri, dstWidth);
                savedUri = saveToCache(activity, bitmap);
                thumbnail = getThumbnail(activity, bitmap);
                bitmap.recycle();
@@ -74,17 +105,16 @@ class ImageTask extends AsyncTask<Uri, Void, ImageTask.ImageTaskResult> {
            }
        } catch (IOException e) {
            if (e.getMessage() != null) {
                errorMessage += ": " + e.getMessage();
                errorMessage = e.getMessage();
            }
        }
        return result;
    }

    @Override
    protected void onPostExecute(@Nullable ImageTaskResult result) {
        super.onPostExecute(result);
    @UiThread
    private void onPostExecute(@Nullable ImageTaskResult result) {
        ImageTaskCallback callback = weakCallback.get();
        if (callback != null) {
        if (callback != null && callback.getActivity() != null) {
            if (result == null) {
                callback.onImageTaskFailure(errorMessage);
            } else {
@@ -102,6 +132,17 @@ class ImageTask extends AsyncTask<Uri, Void, ImageTask.ImageTaskResult> {
        return null;
    }

    /**
     * Try to clean image cache
     * @param result Task result
     */
    private void cleanUp(ImageTaskResult result) {
        Activity activity = getActivity();
        if (result != null && activity != null) {
            clearImageCache(activity.getApplicationContext());
        }
    }

    interface ImageTaskCallback {
        void onImageTaskCompleted(@NonNull Uri uri, @NonNull Bitmap thumbnail);
        void onImageTaskFailure(@NonNull String error);
+1 −1
Original line number Diff line number Diff line
@@ -167,6 +167,7 @@ class LocationHelper {
     * @param singleShot Request single update if true
     * @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 {
        if (Logger.DEBUG) { Log.d(TAG, "[requestProviderUpdates: " + provider + " (" + singleShot + ")]"); }
        try {
@@ -174,7 +175,6 @@ class LocationHelper {
                // request even if provider is disabled to allow users re-enable it later
                locationManager.requestLocationUpdates(provider, minTimeMillis, minDistance, listener, looper);
            } else if (locationManager.isProviderEnabled(provider)) {
                // FIXME: original caller should be rewritten instead?
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                    locationManager.getCurrentLocation(provider, null, runnable -> {
                        if (looper != null) {
+70 −38
Original line number Diff line number Diff line
@@ -12,13 +12,15 @@ package net.fabiszewski.ulogger;
import android.app.Activity;
import android.location.Location;
import android.location.LocationListener;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.annotation.WorkerThread;

import java.lang.ref.WeakReference;

@@ -26,7 +28,7 @@ import java.lang.ref.WeakReference;
/**
 * Task to get location according to user preferences criteria
 */
class LoggerTask extends AsyncTask<Void, Void, Location> implements LocationListener {
class LoggerTask implements LocationListener, Runnable {

    private static final String TAG = LoggerTask.class.getSimpleName();
    private static final int E_OK = 0;
@@ -38,6 +40,11 @@ class LoggerTask extends AsyncTask<Void, Void, Location> implements LocationList
    private final LocationHelper locationHelper;
    private Location location;
    private volatile boolean waiting;
    private boolean isCancelled = false;
    private boolean isRunning = false;

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

    private int error = LocationHelper.LoggerException.E_OK;

@@ -47,7 +54,31 @@ class LoggerTask extends AsyncTask<Void, Void, Location> implements LocationList
    }

    @Override
    protected Location doInBackground(Void... voids) {
    public void run() {
        isRunning = true;
        Location location = doInBackground();
        if (!isCancelled) {
            uiHandler.post(() -> onPostExecute(location));
        }
        isRunning = false;
    }

    public void cancel() {
        if (Logger.DEBUG) { Log.d(TAG, "[task cancelled]"); }
        isCancelled = true;
        quitLoop();
    }

    public boolean isRunning() {
        return isRunning;
    }

    /**
     * Requests location update, waits in loop
     * @return Location or null if none
     */
    @WorkerThread
    private Location doInBackground() {
        if (Logger.DEBUG) { Log.d(TAG, "[doInBackground]"); }
        Activity activity = getActivity();
        if (activity == null) {
@@ -57,52 +88,49 @@ class LoggerTask extends AsyncTask<Void, Void, Location> implements LocationList
            error = E_PERMISSION;
            return null;
        }
        synchronized (lock) {
            waiting = true;
            final long startTime = System.currentTimeMillis();
            try {
                locationHelper.requestSingleUpdate(this, Looper.getMainLooper());
            loop();
                while (waiting) {
                    try {
                        lock.wait(TIMEOUT_MS);
                    } catch (InterruptedException e) {
                        if (Logger.DEBUG) { Log.d(TAG, "[loop interrupted]"); }
                    }
                    if (System.currentTimeMillis() - startTime >= TIMEOUT_MS) {
                        if (Logger.DEBUG) { Log.d(TAG, "[loop timeout]"); }
                        waiting = false;
                    }
                }
                locationHelper.removeUpdates(this);
                return location;
            } catch (LocationHelper.LoggerException e) {
                error = e.getCode();
            }
        }
        return null;
    }

    /**
     * Loop on worker thread
     * Quit loop
     */
    private void loop() {
        waiting = true;
        final long startTime = System.currentTimeMillis();
        while (waiting) {
            if (System.currentTimeMillis() - startTime > TIMEOUT_MS) {
                if (Logger.DEBUG) { Log.d(TAG, "[loop timeout]"); }
                break;
            }
            if (isCancelled()) {
                if (Logger.DEBUG) { Log.d(TAG, "[loop cancelled]"); }
                break;
            }
            try {
                Thread.sleep(500);
            } catch (InterruptedException ignored) {
                break;
            }
    private synchronized void quitLoop() {
        synchronized (lock) {
            waiting = false;
            lock.notifyAll();
        }
    }

    /**
     * Quit loop
     * Execute callback with location result
     * @param location Location
     */
    private void quitLoop() {
        waiting = false;
    }

    @Override
    protected void onPostExecute(Location location) {
        super.onPostExecute(location);
    @UiThread
    private void onPostExecute(Location location) {
        LoggerTaskCallback callback = weakCallback.get();
        if (callback != null) {
        if (callback != null && callback.getActivity() != null) {
            if (error == E_OK && location != null) {
                callback.onLoggerTaskCompleted(location);
            } else {
@@ -133,6 +161,7 @@ class LoggerTask extends AsyncTask<Void, Void, Location> implements LocationList
    }


    @UiThread
    @Override
    public void onLocationChanged(@NonNull Location location) {
        if (Logger.DEBUG) { Log.d(TAG, "[location changed: " + location + "]"); }
@@ -161,10 +190,12 @@ class LoggerTask extends AsyncTask<Void, Void, Location> implements LocationList
        return true;
    }

    @SuppressWarnings({"deprecation", "RedundantSuppression"})
    @UiThread
    @Override
    @SuppressWarnings({"deprecation", "RedundantSuppression"})
    public void onStatusChanged(String provider, int status, Bundle extras) { }

    @UiThread
    @Override
    public void onProviderEnabled(@NonNull String provider) {
        if (Logger.DEBUG) { Log.d(TAG, "[onProviderEnabled: " + provider + "]"); }
@@ -175,6 +206,7 @@ class LoggerTask extends AsyncTask<Void, Void, Location> implements LocationList
        }
    }

    @UiThread
    @Override
    public void onProviderDisabled(@NonNull String provider) {
        if (Logger.DEBUG) { Log.d(TAG, "[onProviderDisabled: " + provider + "]"); }
+18 −21
Original line number Diff line number Diff line
@@ -130,28 +130,25 @@ public class MainActivity extends AppCompatActivity
     */
    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()) {

            case R.id.menu_settings:
        final int id = item.getItemId();
        if (id == R.id.menu_settings) {
            Intent i = new Intent(this, SettingsActivity.class);
            startActivityForResult(i, RESULT_PREFS_UPDATED);
            return true;
            case R.id.menu_about:
        } else if (id == R.id.menu_about) {
            showAbout();
            return true;
            case R.id.menu_export:
        } else if (id == R.id.menu_export) {
            startExport();
            return true;
            case R.id.menu_clear:
        } else if (id == R.id.menu_clear) {
            clearTrack();
            return true;
            case android.R.id.home:
        } else if (id == android.R.id.home) {
            onBackPressed();
            return true;

            default:
                return super.onOptionsItemSelected(item);
        }
        return super.onOptionsItemSelected(item);
    }

    /**
Loading