Loading README.md +4 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -108,6 +108,9 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis // If you stored the "default" account using setCurrentAccount(…) you can get the account by using the following line: final var ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(context); // It is also possible to get the "default" account as a LiveData object: final var ssoAccount$ = SingleAccountHelper.getCurrentSingleSignOnAccount$(context); // Otherwise (for multi-account support you'll have to keep track of the account names yourself. Note: this has to be the name of SingleSignOnAccount.name) AccountImporter.getSingleSignOnAccount(context, accountName); Loading lib/src/main/java/com/nextcloud/android/sso/helper/SingleAccountHelper.java +36 −7 Original line number Diff line number Diff line Loading @@ -24,7 +24,10 @@ import android.app.Activity; 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; import com.nextcloud.android.sso.AccountImporter; import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException; Loading @@ -40,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); Loading @@ -49,24 +53,41 @@ public final class SingleAccountHelper { return accountName; } @WorkerThread public static SingleSignOnAccount getCurrentSingleSignOnAccount(Context context) throws NextcloudFilesAppAccountNotFoundException, NoCurrentAccountSelectedException { return AccountImporter.getSingleSignOnAccount(context, getCurrentAccountName(context)); } /** * Warning: This call is writing synchronously to the disk. * You should use {@link #setCurrentAccountAsync(Context, String)} if possible. * Emits the currently set {@link SingleSignOnAccount} or <code>null</code> if an error occurred. */ @SuppressLint("ApplySharedPref") public static LiveData<SingleSignOnAccount> getCurrentSingleSignOnAccount$(@NonNull Context context) { return new SingleSignOnAccountLiveData(context, AccountImporter.getSharedPreferences(context), PREF_CURRENT_ACCOUNT_STRING); } /** * @deprecated Replaced by {@link #commitCurrentAccount(Context, String)} */ @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) Loading @@ -81,12 +102,20 @@ public final class SingleAccountHelper { AccountImporter.authenticateSingleSignAccount(activity, getCurrentSingleSignOnAccount(activity)); } /** * @deprecated Use {@link #getCurrentSingleSignOnAccount$(Context)} which is lifecycle aware */ @Deprecated(forRemoval = true) public static void registerSharedPreferenceChangeListener(Context context, SharedPreferences.OnSharedPreferenceChangeListener listener) { AccountImporter.getSharedPreferences(context) .registerOnSharedPreferenceChangeListener(listener); } /** * @deprecated Use {@link #getCurrentSingleSignOnAccount$(Context)} which is lifecycle aware */ @Deprecated(forRemoval = true) public static void unregisterSharedPreferenceChangeListener(Context context, SharedPreferences.OnSharedPreferenceChangeListener listener) { AccountImporter.getSharedPreferences(context) Loading lib/src/main/java/com/nextcloud/android/sso/helper/SingleSignOnAccountLiveData.java 0 → 100644 +87 −0 Original line number Diff line number Diff line /* * Nextcloud SingleSignOn * * @author Stefan Niedermann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.nextcloud.android.sso.helper; 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) { 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)) { postValueFromPreferences(); } }; } @Override protected void onActive() { super.onActive(); postValueFromPreferences(); sharedPrefs.registerOnSharedPreferenceChangeListener(preferenceChangeListener); } @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(); } }); } } sample/src/main/java/com/nextcloud/android/sso/sample/MainActivity.java +18 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import com.nextcloud.android.sso.api.NextcloudAPI; import com.nextcloud.android.sso.exceptions.AccountImportCancelledException; import com.nextcloud.android.sso.exceptions.AndroidGetAccountsPermissionNotGranted; import com.nextcloud.android.sso.exceptions.NextcloudFilesAppNotInstalledException; import com.nextcloud.android.sso.helper.SingleAccountHelper; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; Loading Loading @@ -61,6 +62,17 @@ public class MainActivity extends AppCompatActivity { e.printStackTrace(); } }); /* * We can also observe the current SingleSignOnAccount (set via SingleAccountHelper) with LiveData */ 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 Loading @@ -71,6 +83,12 @@ public class MainActivity extends AppCompatActivity { AccountImporter.onActivityResult(requestCode, resultCode, data, this, ssoAccount -> { Log.i(TAG, "Imported account: " + ssoAccount.name); /* * A little helper to store the currently selected account. * We can query this later if we want to keep working with it. */ SingleAccountHelper.commitCurrentAccount(this, ssoAccount.name); /* Network requests need to be performed on a background thread */ executor.submit(() -> { runOnUiThread(() -> ((TextView) findViewById(R.id.result)).setText(R.string.loading)); Loading Loading
README.md +4 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -108,6 +108,9 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis // If you stored the "default" account using setCurrentAccount(…) you can get the account by using the following line: final var ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(context); // It is also possible to get the "default" account as a LiveData object: final var ssoAccount$ = SingleAccountHelper.getCurrentSingleSignOnAccount$(context); // Otherwise (for multi-account support you'll have to keep track of the account names yourself. Note: this has to be the name of SingleSignOnAccount.name) AccountImporter.getSingleSignOnAccount(context, accountName); Loading
lib/src/main/java/com/nextcloud/android/sso/helper/SingleAccountHelper.java +36 −7 Original line number Diff line number Diff line Loading @@ -24,7 +24,10 @@ import android.app.Activity; 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; import com.nextcloud.android.sso.AccountImporter; import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException; Loading @@ -40,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); Loading @@ -49,24 +53,41 @@ public final class SingleAccountHelper { return accountName; } @WorkerThread public static SingleSignOnAccount getCurrentSingleSignOnAccount(Context context) throws NextcloudFilesAppAccountNotFoundException, NoCurrentAccountSelectedException { return AccountImporter.getSingleSignOnAccount(context, getCurrentAccountName(context)); } /** * Warning: This call is writing synchronously to the disk. * You should use {@link #setCurrentAccountAsync(Context, String)} if possible. * Emits the currently set {@link SingleSignOnAccount} or <code>null</code> if an error occurred. */ @SuppressLint("ApplySharedPref") public static LiveData<SingleSignOnAccount> getCurrentSingleSignOnAccount$(@NonNull Context context) { return new SingleSignOnAccountLiveData(context, AccountImporter.getSharedPreferences(context), PREF_CURRENT_ACCOUNT_STRING); } /** * @deprecated Replaced by {@link #commitCurrentAccount(Context, String)} */ @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) Loading @@ -81,12 +102,20 @@ public final class SingleAccountHelper { AccountImporter.authenticateSingleSignAccount(activity, getCurrentSingleSignOnAccount(activity)); } /** * @deprecated Use {@link #getCurrentSingleSignOnAccount$(Context)} which is lifecycle aware */ @Deprecated(forRemoval = true) public static void registerSharedPreferenceChangeListener(Context context, SharedPreferences.OnSharedPreferenceChangeListener listener) { AccountImporter.getSharedPreferences(context) .registerOnSharedPreferenceChangeListener(listener); } /** * @deprecated Use {@link #getCurrentSingleSignOnAccount$(Context)} which is lifecycle aware */ @Deprecated(forRemoval = true) public static void unregisterSharedPreferenceChangeListener(Context context, SharedPreferences.OnSharedPreferenceChangeListener listener) { AccountImporter.getSharedPreferences(context) Loading
lib/src/main/java/com/nextcloud/android/sso/helper/SingleSignOnAccountLiveData.java 0 → 100644 +87 −0 Original line number Diff line number Diff line /* * Nextcloud SingleSignOn * * @author Stefan Niedermann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.nextcloud.android.sso.helper; 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) { 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)) { postValueFromPreferences(); } }; } @Override protected void onActive() { super.onActive(); postValueFromPreferences(); sharedPrefs.registerOnSharedPreferenceChangeListener(preferenceChangeListener); } @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(); } }); } }
sample/src/main/java/com/nextcloud/android/sso/sample/MainActivity.java +18 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import com.nextcloud.android.sso.api.NextcloudAPI; import com.nextcloud.android.sso.exceptions.AccountImportCancelledException; import com.nextcloud.android.sso.exceptions.AndroidGetAccountsPermissionNotGranted; import com.nextcloud.android.sso.exceptions.NextcloudFilesAppNotInstalledException; import com.nextcloud.android.sso.helper.SingleAccountHelper; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; Loading Loading @@ -61,6 +62,17 @@ public class MainActivity extends AppCompatActivity { e.printStackTrace(); } }); /* * We can also observe the current SingleSignOnAccount (set via SingleAccountHelper) with LiveData */ 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 Loading @@ -71,6 +83,12 @@ public class MainActivity extends AppCompatActivity { AccountImporter.onActivityResult(requestCode, resultCode, data, this, ssoAccount -> { Log.i(TAG, "Imported account: " + ssoAccount.name); /* * A little helper to store the currently selected account. * We can query this later if we want to keep working with it. */ SingleAccountHelper.commitCurrentAccount(this, ssoAccount.name); /* Network requests need to be performed on a background thread */ executor.submit(() -> { runOnUiThread(() -> ((TextView) findViewById(R.id.result)).setText(R.string.loading)); Loading