Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e8485704 authored by Stefan Niedermann's avatar Stefan Niedermann
Browse files

feat(helper): LiveData now emits NULL if an error occurs, @WorkerThread for synchronous operations

parent ce986e7e
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -75,7 +75,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
            // As this library supports multiple accounts we created some helper methods if you only want to use one.
            // The following line stores the selected account as the "default" account which can be queried by using
            // the SingleAccountHelper.getCurrentSingleSignOnAccount(context) method
            SingleAccountHelper.setCurrentAccount(context, account.name);
            SingleAccountHelper.commitCurrentAccount(context, account.name);

            // Get the "default" account
            SingleSignOnAccount ssoAccount = null;
+20 −5
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.content.Context;
import android.content.SharedPreferences;

import androidx.annotation.NonNull;
import androidx.annotation.WorkerThread;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.LiveData;

@@ -42,6 +43,7 @@ public final class SingleAccountHelper {
    private SingleAccountHelper() {
    }

    @WorkerThread
    private static String getCurrentAccountName(Context context) throws NoCurrentAccountSelectedException {
        SharedPreferences mPrefs = AccountImporter.getSharedPreferences(context);
        String accountName = mPrefs.getString(PREF_CURRENT_ACCOUNT_STRING, null);
@@ -51,28 +53,41 @@ public final class SingleAccountHelper {
        return accountName;
    }

    @WorkerThread
    public static SingleSignOnAccount getCurrentSingleSignOnAccount(Context context)
            throws NextcloudFilesAppAccountNotFoundException, NoCurrentAccountSelectedException {
        return AccountImporter.getSingleSignOnAccount(context, getCurrentAccountName(context));
    }

    /**
     * Emits the currently set {@link SingleSignOnAccount} or <code>null</code> if an error occurred.
     */
    public static LiveData<SingleSignOnAccount> getCurrentSingleSignOnAccount$(@NonNull Context context) {
        return new SingleSignOnAccountLiveData(context, AccountImporter.getSharedPreferences(context), PREF_CURRENT_ACCOUNT_STRING);
    }

    /**
     * Warning: This call is writing synchronously to the disk.
     * You should use {@link #setCurrentAccountAsync(Context, String)} if possible.
     * @deprecated Replaced by {@link #commitCurrentAccount(Context, String)}
     */
    @SuppressLint("ApplySharedPref")
    @Deprecated(forRemoval = true)
    public static void setCurrentAccount(Context context, String accountName) {
        commitCurrentAccount(context, accountName);
    }

    /**
     * Warning: This call is <em>synchronous</em>.
     * Consider using {@link #applyCurrentAccount(Context, String)} if possible.
     */
    @SuppressLint("ApplySharedPref")
    @WorkerThread
    public static void commitCurrentAccount(Context context, String accountName) {
        AccountImporter.getSharedPreferences(context)
                .edit()
                .putString(PREF_CURRENT_ACCOUNT_STRING, accountName)
                .commit();
    }

    public static void setCurrentAccountAsync(Context context, String accountName) {
    public static void applyCurrentAccount(Context context, String accountName) {
        AccountImporter.getSharedPreferences(context)
                .edit()
                .putString(PREF_CURRENT_ACCOUNT_STRING, accountName)
+31 −18
Original line number Diff line number Diff line
@@ -19,34 +19,44 @@

package com.nextcloud.android.sso.helper;

import static com.nextcloud.android.sso.helper.SingleAccountHelper.getCurrentSingleSignOnAccount;

import android.content.Context;
import android.content.SharedPreferences;

import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.LiveData;

import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
import com.nextcloud.android.sso.exceptions.NoCurrentAccountSelectedException;
import com.nextcloud.android.sso.model.SingleSignOnAccount;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SingleSignOnAccountLiveData extends LiveData<SingleSignOnAccount> {

    private final Context context;
    private final SharedPreferences sharedPrefs;
    private final SharedPreferences.OnSharedPreferenceChangeListener preferenceChangeListener;
    private final ExecutorService executor;

    SingleSignOnAccountLiveData(@NonNull Context context, @NonNull SharedPreferences sharedPrefs, @NonNull String key) {
    SingleSignOnAccountLiveData(@NonNull Context context,
                                @NonNull SharedPreferences sharedPrefs,
                                @NonNull String key) {
        this(context, sharedPrefs, key, Executors.newSingleThreadExecutor());
    }

    @VisibleForTesting
    SingleSignOnAccountLiveData(@NonNull Context context,
                                @NonNull SharedPreferences sharedPrefs,
                                @NonNull String key,
                                @NonNull ExecutorService executor) {
        this.context = context;
        this.sharedPrefs = sharedPrefs;
        this.executor = executor;
        this.preferenceChangeListener = (changedPrefs, changedKey) -> {
            if (key.equals(changedKey)) {
                try {
                    setValue(getValueFromPreferences());
                } catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) {
                    e.printStackTrace();
                }
                postValueFromPreferences();
            }
        };
    }
@@ -54,21 +64,24 @@ public class SingleSignOnAccountLiveData extends LiveData<SingleSignOnAccount> {
    @Override
    protected void onActive() {
        super.onActive();
        try {
            setValue(getValueFromPreferences());
        } catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) {
            e.printStackTrace();
        }
        postValueFromPreferences();
        sharedPrefs.registerOnSharedPreferenceChangeListener(preferenceChangeListener);
    }

    private SingleSignOnAccount getValueFromPreferences() throws NextcloudFilesAppAccountNotFoundException, NoCurrentAccountSelectedException {
        return getCurrentSingleSignOnAccount(context);
    }

    @Override
    protected void onInactive() {
        sharedPrefs.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener);
        super.onInactive();
    }

    private void postValueFromPreferences() {
        executor.submit(() -> {
            try {
                postValue(SingleAccountHelper.getCurrentSingleSignOnAccount(context));
            } catch (NoCurrentAccountSelectedException | NextcloudFilesAppAccountNotFoundException e) {
                postValue(null);
                e.printStackTrace();
            }
        });
    }
}
+8 −3
Original line number Diff line number Diff line
@@ -66,8 +66,13 @@ public class MainActivity extends AppCompatActivity {
        /*
         * We can also observe the current SingleSignOnAccount (set via SingleAccountHelper) with LiveData
         */
        SingleAccountHelper.getCurrentSingleSignOnAccount$(this)
                .observe(this, ssoAccount -> Log.i(TAG, "New SingleSignOnAccount set: " + ssoAccount.name));
        SingleAccountHelper.getCurrentSingleSignOnAccount$(this).observe(this, ssoAccount -> {
            if (ssoAccount == null) {
                Log.i(TAG, "Currently no SingleSignOnAccount selected.");
            } else {
                Log.i(TAG, "New SingleSignOnAccount set: " + ssoAccount.name);
            }
        });
    }

    @Override
@@ -82,7 +87,7 @@ public class MainActivity extends AppCompatActivity {
                 * A little helper to store the currently selected account.
                 * We can query this later if we want to keep working with it.
                 */
                SingleAccountHelper.setCurrentAccountAsync(this, ssoAccount.name);
                SingleAccountHelper.commitCurrentAccount(this, ssoAccount.name);

                /* Network requests need to be performed on a background thread */
                executor.submit(() -> {