Merge pull request #3895 from nextcloud/ezaquarii/user-account-manager

Create UserAccountManager and move getAccounts()
This commit is contained in:
Andy Scherzinger 2019-04-13 08:42:22 +02:00 committed by GitHub
commit 4442d5a338
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 642 additions and 243 deletions

View File

@ -22,4 +22,7 @@
</Match>
<Bug pattern="PATH_TRAVERSAL_IN" />
<Bug pattern="ANDROID_EXTERNAL_FILE_ACCESS" />
<!-- This is unmanageable for now dur to large amount of interconnected static state -->
<Bug pattern="FCCD_FIND_CLASS_CIRCULAR_DEPENDENCY"/>
</FindBugsFilter>

View File

@ -1 +1 @@
470
441

View File

@ -0,0 +1,26 @@
/*
* Nextcloud Android client application
*
* @author Chris Narkiewicz
* Copyright (C) 2919 Chris Narkiewicz <hello@ezaquarii.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or 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 AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.nextcloud.client.di;
import dagger.Module;
@Module
abstract class VariantComponentsModule {
}

View File

@ -2,7 +2,9 @@
* Nextcloud Android client application
*
* @author Mario Danic
* @author Chris Narkiewicz
* Copyright (C) 2017 Mario Danic
* Copyright (C) 2019 Chris Narkiewicz
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@ -22,6 +24,7 @@ package com.owncloud.android.utils;
import android.content.Context;
import com.nextcloud.client.account.UserAccountManager;
import com.owncloud.android.MainApp;
import com.owncloud.android.datamodel.SignatureVerification;
import com.nextcloud.client.preferences.AppPreferencesImpl;
@ -34,11 +37,11 @@ public final class PushUtils {
private PushUtils() {
}
public static void pushRegistrationToServer(final String pushToken) {
public static void pushRegistrationToServer(final UserAccountManager accountManager, final String pushToken) {
// do nothing
}
public static void reinitKeys() {
public static void reinitKeys(UserAccountManager accountManager) {
Context context = MainApp.getAppContext();
AppPreferencesImpl.fromContext(context).setKeysReInitEnabled();
}
@ -47,7 +50,12 @@ public final class PushUtils {
return null;
}
public static SignatureVerification verifySignature(Context context, byte[] signatureBytes, byte[] subjectBytes) {
public static SignatureVerification verifySignature(
final Context context,
final UserAccountManager accountManager,
final byte[] signatureBytes,
final byte[] subjectBytes
) {
return null;
}

View File

@ -0,0 +1,30 @@
/*
* Nextcloud Android client application
*
* @author Chris Narkiewicz
* Copyright (C) 2919 Chris Narkiewicz <hello@ezaquarii.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or 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 AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.nextcloud.client.di;
import com.owncloud.android.services.firebase.NCFirebaseInstanceIDService;
import dagger.Module;
import dagger.android.ContributesAndroidInjector;
@Module
abstract class VariantComponentsModule {
@ContributesAndroidInjector abstract NCFirebaseInstanceIDService ncFirebaseInstanceIDService();
}

View File

@ -23,19 +23,25 @@ import android.text.TextUtils;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.client.preferences.AppPreferences;
import com.nextcloud.client.preferences.AppPreferencesImpl;
import com.owncloud.android.R;
import com.owncloud.android.utils.PushUtils;
import javax.inject.Inject;
import dagger.android.AndroidInjection;
public class NCFirebaseInstanceIDService extends FirebaseInstanceIdService {
private AppPreferences preferences;
@Inject AppPreferences preferences;
@Inject UserAccountManager accountManager;
@Override
public void onCreate() {
super.onCreate();
preferences = AppPreferencesImpl.fromContext(this);
AndroidInjection.inject(this);
}
@Override
@ -43,7 +49,7 @@ public class NCFirebaseInstanceIDService extends FirebaseInstanceIdService {
//You can implement this method to store the token on your server
if (!TextUtils.isEmpty(getResources().getString(R.string.push_server_url))) {
preferences.setPushToken(FirebaseInstanceId.getInstance().getToken());
PushUtils.pushRegistrationToServer(preferences.getPushToken());
PushUtils.pushRegistrationToServer(accountManager, preferences.getPushToken());
}
}
}

View File

@ -2,7 +2,9 @@
* Nextcloud Android client application
*
* @author Mario Danic
* @author Chris Narkiewicz
* Copyright (C) 2017-2018 Mario Danic
* Copyright (C) 2019 Chris Narkiewicz
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@ -29,6 +31,7 @@ import android.util.Base64;
import android.util.Log;
import com.google.gson.Gson;
import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.client.preferences.AppPreferences;
import com.nextcloud.client.preferences.AppPreferencesImpl;
import com.owncloud.android.MainApp;
@ -194,7 +197,7 @@ public final class PushUtils {
}
}
public static void pushRegistrationToServer(final String token) {
public static void pushRegistrationToServer(final UserAccountManager accountManager, final String token) {
arbitraryDataProvider = new ArbitraryDataProvider(MainApp.getAppContext().getContentResolver());
if (!TextUtils.isEmpty(MainApp.getAppContext().getResources().getString(R.string.push_server_url)) &&
@ -213,7 +216,7 @@ public final class PushUtils {
String providerValue;
PushConfigurationState accountPushData = null;
Gson gson = new Gson();
for (Account account : AccountUtils.getAccounts(context)) {
for (Account account : accountManager.getAccounts()) {
providerValue = arbitraryDataProvider.getValue(account, KEY_PUSH);
if (!TextUtils.isEmpty(providerValue)) {
accountPushData = gson.fromJson(providerValue,
@ -359,9 +362,9 @@ public final class PushUtils {
return -1;
}
public static void reinitKeys() {
public static void reinitKeys(final UserAccountManager accountManager) {
Context context = MainApp.getAppContext();
Account[] accounts = AccountUtils.getAccounts(context);
Account[] accounts = accountManager.getAccounts();
for (Account account : accounts) {
deleteRegistrationForAccount(account);
}
@ -375,7 +378,7 @@ public final class PushUtils {
AppPreferences preferences = AppPreferencesImpl.fromContext(context);
String pushToken = preferences.getPushToken();
pushRegistrationToServer(pushToken);
pushRegistrationToServer(accountManager, pushToken);
preferences.setKeysReInitEnabled();
}
@ -411,13 +414,18 @@ public final class PushUtils {
}
}
public static SignatureVerification verifySignature(Context context, byte[] signatureBytes, byte[] subjectBytes) {
public static SignatureVerification verifySignature(
final Context context,
final UserAccountManager accountManager,
final byte[] signatureBytes,
final byte[] subjectBytes
) {
Signature signature = null;
PublicKey publicKey;
SignatureVerification signatureVerification = new SignatureVerification();
signatureVerification.setSignatureValid(false);
Account[] accounts = AccountUtils.getAccounts(context);
Account[] accounts = accountManager.getAccounts();
ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProvider(context.getContentResolver());
String arbitraryValue;

View File

@ -0,0 +1,65 @@
/*
* Nextcloud Android client application
*
* @author Chris Narkiewicz
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or 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 AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.nextcloud.client.account;
import android.accounts.Account;
import androidx.annotation.NonNull;
public interface UserAccountManager {
int ACCOUNT_VERSION = 1;
int ACCOUNT_VERSION_WITH_PROPER_ID = 2;
String ACCOUNT_USES_STANDARD_PASSWORD = "ACCOUNT_USES_STANDARD_PASSWORD";
/**
* Get configured NextCloud's user accounts.
*
* @return Array of accounts or empty array, if accounts are not configured.
*/
@NonNull
Account[] getAccounts();
/**
* Update the accounts in AccountManager to meet the current
* version of accounts expected by the app, if needed.
* <p>
* Introduced to handle a change in the structure of stored account names
* needed to allow different Nextcloud servers in the same domain, but not in
* the same path.
*/
void updateAccountVersion();
/**
* Extract username from account.
*
* Full account name is in form of "username@nextcloud.domain".
*
* @param account Account instance
* @return User name (without domain) or null, if name cannot be extracted.
*/
static String getUsername(Account account) {
if (account != null && account.name != null) {
return account.name.substring(0, account.name.lastIndexOf('@'));
} else {
return null;
}
}
}

View File

@ -0,0 +1,196 @@
/*
* Nextcloud Android client application
*
* @author Chris Narkiewicz
* Copyright (C) 2019 Chris Narkiewicz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or 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 AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.nextcloud.client.account;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.Context;
import android.net.Uri;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.authentication.AccountUtils;
import com.owncloud.android.lib.common.OwnCloudAccount;
import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
import com.owncloud.android.lib.common.UserInfo;
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.resources.users.GetRemoteUserInfoOperation;
import javax.inject.Inject;
import androidx.annotation.NonNull;
public class UserAccountManagerImpl implements UserAccountManager {
private static final String TAG = AccountUtils.class.getSimpleName();
private static final String PREF_SELECT_OC_ACCOUNT = "select_oc_account";
private Context context;
private AccountManager accountManager;
@Inject
public UserAccountManagerImpl(Context context, AccountManager accountManager) {
this.context = context;
this.accountManager = accountManager;
}
@Override
@NonNull
public Account[] getAccounts() {
return accountManager.getAccountsByType(getAccountType());
}
public void updateAccountVersion() {
Account currentAccount = AccountUtils.getCurrentOwnCloudAccount(context);
if (currentAccount == null) {
return;
}
final String currentAccountVersion = accountManager.getUserData(currentAccount, com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_OC_ACCOUNT_VERSION);
final boolean needsUpdate = !String.valueOf(ACCOUNT_VERSION_WITH_PROPER_ID).equalsIgnoreCase(currentAccountVersion);
if (!needsUpdate) {
return;
}
Log_OC.i(TAG, "Upgrading accounts to account version #" + ACCOUNT_VERSION_WITH_PROPER_ID);
Account[] ocAccounts = accountManager.getAccountsByType(MainApp.getAccountType(context));
String serverUrl;
String username;
String displayName;
String newAccountName;
Account newAccount;
GetRemoteUserInfoOperation remoteUserNameOperation = new GetRemoteUserInfoOperation();
for (Account account : ocAccounts) {
// build new account name
serverUrl = accountManager.getUserData(account, com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_OC_BASE_URL);
// update user name
try {
OwnCloudAccount ocAccount = new OwnCloudAccount(account, context);
OwnCloudClient client = OwnCloudClientManagerFactory.getDefaultSingleton()
.getClientFor(ocAccount, context);
RemoteOperationResult result = remoteUserNameOperation.execute(client);
if (result.isSuccess()) {
UserInfo userInfo = (UserInfo) result.getData().get(0);
username = userInfo.id;
displayName = userInfo.displayName;
} else {
// skip account, try it next time
Log_OC.e(TAG, "Error while getting username for account: " + account.name);
continue;
}
} catch (Exception e) {
Log_OC.e(TAG, "Error while getting username: " + e.getMessage());
continue;
}
newAccountName = com.owncloud.android.lib.common.accounts.AccountUtils.
buildAccountName(Uri.parse(serverUrl), username);
// migrate to a new account, if needed
if (!newAccountName.equals(account.name)) {
newAccount = migrateAccount(context, currentAccount, accountManager, serverUrl, newAccountName,
account);
} else {
// servers which base URL is in the root of their domain need no change
Log_OC.d(TAG, account.name + " needs no upgrade ");
newAccount = account;
}
accountManager.setUserData(newAccount, com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_DISPLAY_NAME, displayName);
accountManager.setUserData(newAccount, com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_USER_ID, username);
// at least, upgrade account version
Log_OC.d(TAG, "Setting version " + ACCOUNT_VERSION_WITH_PROPER_ID + " to " + newAccountName);
accountManager.setUserData(newAccount, com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_OC_ACCOUNT_VERSION,
Integer.toString(ACCOUNT_VERSION_WITH_PROPER_ID));
}
}
@NonNull
private Account migrateAccount(Context context, Account currentAccount, AccountManager accountMgr,
String serverUrl, String newAccountName, Account account) {
Log_OC.d(TAG, "Upgrading " + account.name + " to " + newAccountName);
// create the new account
Account newAccount = new Account(newAccountName, MainApp.getAccountType(context));
String password = accountMgr.getPassword(account);
accountMgr.addAccountExplicitly(newAccount, (password != null) ? password : "", null);
// copy base URL
accountMgr.setUserData(newAccount, com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_OC_BASE_URL, serverUrl);
// copy server version
accountMgr.setUserData(
newAccount,
com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_OC_VERSION,
accountMgr.getUserData(account, com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_OC_VERSION)
);
// copy cookies
accountMgr.setUserData(
newAccount,
com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_COOKIES,
accountMgr.getUserData(account, com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_COOKIES)
);
// copy type of authentication
final String isSamlStr = accountMgr.getUserData(account, com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_SUPPORTS_SAML_WEB_SSO);
if (Boolean.parseBoolean(isSamlStr)) {
accountMgr.setUserData(newAccount, com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_SUPPORTS_SAML_WEB_SSO, "TRUE");
}
final String isOauthStr = accountMgr.getUserData(account, com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_SUPPORTS_OAUTH2);
if (Boolean.parseBoolean(isOauthStr)) {
accountMgr.setUserData(newAccount, com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_SUPPORTS_OAUTH2, "TRUE");
}
/* TODO - study if it's possible to run this method in a background thread to copy the authToken
if (isOAuth || isSaml) {
accountMgr.setAuthToken(newAccount, mAuthTokenType, mAuthToken);
}
*/
// don't forget the account saved in preferences as the current one
if (currentAccount.name.equals(account.name)) {
AccountUtils.setCurrentOwnCloudAccount(context, newAccountName);
}
// remove the old account
accountMgr.removeAccount(account, null, null);
// will assume it succeeds, not a big deal otherwise
return newAccount;
}
private String getAccountType() {
return context.getString(R.string.account_type);
}
}

View File

@ -20,25 +20,38 @@
package com.nextcloud.client.di;
import android.accounts.AccountManager;
import android.app.Application;
import android.content.Context;
import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.client.account.UserAccountManagerImpl;
import com.nextcloud.client.preferences.AppPreferences;
import com.nextcloud.client.preferences.AppPreferencesImpl;
import dagger.Module;
import dagger.Provides;
@Module(includes = {ComponentsModule.class})
@Module(includes = {ComponentsModule.class, VariantComponentsModule.class})
class AppModule {
@Provides
AccountManager accountManager(Application application) {
return (AccountManager)application.getSystemService(Context.ACCOUNT_SERVICE);
}
@Provides
Context context(Application application) {
return application.getApplicationContext();
return application;
}
@Provides
AppPreferences preferences(Application application) {
return AppPreferencesImpl.fromContext(application);
}
@Provides
UserAccountManager userAccountManager(Context context, AccountManager accountManager) {
return new UserAccountManagerImpl(context, accountManager);
}
}

View File

@ -22,6 +22,8 @@ package com.nextcloud.client.di;
import com.owncloud.android.authentication.AuthenticatorActivity;
import com.owncloud.android.authentication.DeepLinkLoginActivity;
import com.owncloud.android.files.BootupBroadcastReceiver;
import com.owncloud.android.providers.DocumentsStorageProvider;
import com.owncloud.android.ui.activities.ActivitiesActivity;
import com.owncloud.android.ui.activity.ConflictsResolveActivity;
import com.owncloud.android.ui.activity.ContactsPreferenceActivity;
@ -109,4 +111,8 @@ abstract class ComponentsModule {
@ContributesAndroidInjector abstract FileDetailFragment fileDetailFragment();
@ContributesAndroidInjector abstract LocalFileListFragment localFileListFragment();
@ContributesAndroidInjector abstract OCFileListFragment ocFileListFragment();
@ContributesAndroidInjector abstract BootupBroadcastReceiver bootupBroadcastReceiver();
@ContributesAndroidInjector abstract DocumentsStorageProvider documentsStorageProvider();
}

View File

@ -2,7 +2,9 @@
* ownCloud Android client application
*
* @author David A. Velasco
* @author Chris Narkiewicz Chris Narkiewicz
* Copyright (C) 2016 ownCloud Inc.
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
@ -71,14 +73,8 @@ public final class AppPreferencesImpl implements AppPreferences {
private final SharedPreferences preferences;
public static AppPreferences fromContext(Context context) {
Context appContext = context.getApplicationContext();
SharedPreferences prefs = getDefaultSharedPreferences(appContext);
return new AppPreferencesImpl(appContext, prefs);
}
private static SharedPreferences getDefaultSharedPreferences(Context context) {
return android.preference.PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
SharedPreferences prefs = android.preference.PreferenceManager.getDefaultSharedPreferences(context);
return new AppPreferencesImpl(context, prefs);
}
AppPreferencesImpl(Context appContext, SharedPreferences preferences) {

View File

@ -3,7 +3,9 @@
*
* @author masensio
* @author David A. Velasco
* @author Chris Narkiewicz
* Copyright (C) 2015 ownCloud Inc.
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
@ -26,6 +28,8 @@ import android.app.Activity;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@ -40,6 +44,7 @@ import android.view.WindowManager;
import com.evernote.android.job.JobManager;
import com.evernote.android.job.JobRequest;
import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.client.di.ActivityInjector;
import com.nextcloud.client.di.DaggerAppComponent;
import com.nextcloud.client.preferences.AppPreferences;
@ -89,6 +94,8 @@ import androidx.multidex.MultiDexApplication;
import dagger.android.AndroidInjector;
import dagger.android.DispatchingAndroidInjector;
import dagger.android.HasActivityInjector;
import dagger.android.HasBroadcastReceiverInjector;
import dagger.android.HasContentProviderInjector;
import dagger.android.HasServiceInjector;
import dagger.android.support.HasSupportFragmentInjector;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
@ -105,7 +112,9 @@ import static com.owncloud.android.ui.activity.ContactsPreferenceActivity.PREFER
public class MainApp extends MultiDexApplication implements
HasActivityInjector,
HasSupportFragmentInjector,
HasServiceInjector {
HasServiceInjector,
HasContentProviderInjector,
HasBroadcastReceiverInjector {
public static final OwnCloudVersion OUTDATED_SERVER_VERSION = OwnCloudVersion.nextcloud_14;
public static final OwnCloudVersion MINIMUM_SUPPORTED_SERVER_VERSION = OwnCloudVersion.nextcloud_12;
@ -137,24 +146,37 @@ public class MainApp extends MultiDexApplication implements
@Inject
DispatchingAndroidInjector<Service> dispatchingServiceInjector;
@Inject
DispatchingAndroidInjector<ContentProvider> dispatchingContentProviderInjector;
@Inject
DispatchingAndroidInjector<BroadcastReceiver> dispatchingBroadcastReceiverInjector;
@Inject
UserAccountManager accountManager;
private PassCodeManager passCodeManager;
@SuppressWarnings("unused")
private boolean mBound;
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
DaggerAppComponent.builder()
.application(this)
.build()
.inject(this);
}
@SuppressFBWarnings("ST")
@Override
public void onCreate() {
super.onCreate();
DaggerAppComponent.builder()
.application(this)
.build()
.inject(this);
registerActivityLifecycleCallbacks(new ActivityInjector());
JobManager.create(this).addJobCreator(new NCJobCreator());
JobManager.create(this).addJobCreator(new NCJobCreator(getApplicationContext(), accountManager, preferences));
MainApp.mContext = getApplicationContext();
new SecurityUtils();
@ -195,8 +217,8 @@ public class MainApp extends MultiDexApplication implements
}
}
initSyncOperations();
initContactsBackup();
initSyncOperations(accountManager);
initContactsBackup(accountManager);
notificationChannels();
@ -256,9 +278,9 @@ public class MainApp extends MultiDexApplication implements
});
}
public static void initContactsBackup() {
public static void initContactsBackup(UserAccountManager accountManager) {
ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProvider(mContext.getContentResolver());
Account[] accounts = AccountUtils.getAccounts(mContext);
Account[] accounts = accountManager.getAccounts();
for (Account account : accounts) {
if (arbitraryDataProvider.getBooleanValue(account, PREFERENCE_CONTACTS_AUTOMATIC_BACKUP)) {
@ -320,7 +342,7 @@ public class MainApp extends MultiDexApplication implements
}
}
public static void initSyncOperations() {
public static void initSyncOperations(UserAccountManager accountManager) {
updateToAutoUpload();
cleanOldEntries();
updateAutoUploadEntries();
@ -338,17 +360,18 @@ public class MainApp extends MultiDexApplication implements
initiateExistingAutoUploadEntries();
FilesSyncHelper.scheduleFilesSyncIfNeeded(mContext);
FilesSyncHelper.restartJobsIfNeeded();
FilesSyncHelper.restartJobsIfNeeded(accountManager);
FilesSyncHelper.scheduleOfflineSyncIfNeeded();
ReceiversHelper.registerNetworkChangeReceiver();
ReceiversHelper.registerNetworkChangeReceiver(accountManager);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
ReceiversHelper.registerPowerChangeReceiver();
ReceiversHelper.registerPowerChangeReceiver(accountManager
);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ReceiversHelper.registerPowerSaveReceiver();
ReceiversHelper.registerPowerSaveReceiver(accountManager);
}
}
@ -698,4 +721,14 @@ public class MainApp extends MultiDexApplication implements
public AndroidInjector<Service> serviceInjector() {
return dispatchingServiceInjector;
}
@Override
public AndroidInjector<ContentProvider> contentProviderInjector() {
return dispatchingContentProviderInjector;
}
@Override
public AndroidInjector<BroadcastReceiver> broadcastReceiverInjector() {
return dispatchingBroadcastReceiverInjector;
}
}

View File

@ -103,7 +103,7 @@ public final class AccountUtils {
return defaultAccount;
}
public static Account[] getAccounts(Context context) {
private static Account[] getAccounts(Context context) {
AccountManager accountManager = AccountManager.get(context);
return accountManager.getAccountsByType(MainApp.getAccountType(context));
}
@ -131,20 +131,6 @@ public final class AccountUtils {
return false;
}
/**
* returns the user's name based on the account name.
*
* @param accountName the account name
* @return the user's name
*/
public static String getAccountUsername(String accountName) {
if (accountName != null) {
return accountName.substring(0, accountName.lastIndexOf('@'));
} else {
return null;
}
}
/**
* Returns owncloud account identified by accountName or null if it does not exist.
* @param context the context
@ -212,141 +198,6 @@ public final class AccountUtils {
return getServerVersion(account).isSearchSupported();
}
/**
* Update the accounts in AccountManager to meet the current version of accounts expected by the app, if needed.
* <p>
* Introduced to handle a change in the structure of stored account names needed to allow different OC servers in
* the same domain, but not in the same path.
*
* @param context Used to access the AccountManager.
*/
public static void updateAccountVersion(Context context) {
Account currentAccount = AccountUtils.getCurrentOwnCloudAccount(context);
AccountManager accountMgr = AccountManager.get(context);
if (currentAccount != null) {
String currentAccountVersion = accountMgr.getUserData(currentAccount, Constants.KEY_OC_ACCOUNT_VERSION);
if (!String.valueOf(ACCOUNT_VERSION_WITH_PROPER_ID).equalsIgnoreCase(currentAccountVersion)) {
Log_OC.i(TAG, "Upgrading accounts to account version #" + ACCOUNT_VERSION_WITH_PROPER_ID);
Account[] ocAccounts = accountMgr.getAccountsByType(MainApp.getAccountType(context));
String serverUrl;
String username;
String displayName;
String newAccountName;
Account newAccount;
GetRemoteUserInfoOperation remoteUserNameOperation = new GetRemoteUserInfoOperation();
for (Account account : ocAccounts) {
// build new account name
serverUrl = accountMgr.getUserData(account, Constants.KEY_OC_BASE_URL);
// update user name
try {
OwnCloudAccount ocAccount = new OwnCloudAccount(account, context);
OwnCloudClient client = OwnCloudClientManagerFactory.getDefaultSingleton()
.getClientFor(ocAccount, context);
RemoteOperationResult result = remoteUserNameOperation.execute(client);
if (result.isSuccess()) {
UserInfo userInfo = (UserInfo) result.getData().get(0);
username = userInfo.id;
displayName = userInfo.displayName;
} else {
// skip account, try it next time
Log_OC.e(TAG, "Error while getting username for account: " + account.name);
continue;
}
} catch (Exception e) {
Log_OC.e(TAG, "Error while getting username: " + e.getMessage());
continue;
}
newAccountName = com.owncloud.android.lib.common.accounts.AccountUtils.
buildAccountName(Uri.parse(serverUrl), username);
// migrate to a new account, if needed
if (!newAccountName.equals(account.name)) {
newAccount = migrateAccount(context, currentAccount, accountMgr, serverUrl, newAccountName,
account);
} else {
// servers which base URL is in the root of their domain need no change
Log_OC.d(TAG, account.name + " needs no upgrade ");
newAccount = account;
}
accountMgr.setUserData(newAccount, Constants.KEY_DISPLAY_NAME, displayName);
accountMgr.setUserData(newAccount, Constants.KEY_USER_ID, username);
// at least, upgrade account version
Log_OC.d(TAG, "Setting version " + ACCOUNT_VERSION_WITH_PROPER_ID + " to " + newAccountName);
accountMgr.setUserData(newAccount, Constants.KEY_OC_ACCOUNT_VERSION,
Integer.toString(ACCOUNT_VERSION_WITH_PROPER_ID));
}
}
}
}
@NonNull
private static Account migrateAccount(Context context, Account currentAccount, AccountManager accountMgr,
String serverUrl, String newAccountName, Account account) {
Log_OC.d(TAG, "Upgrading " + account.name + " to " + newAccountName);
// create the new account
Account newAccount = new Account(newAccountName, MainApp.getAccountType(context));
String password = accountMgr.getPassword(account);
accountMgr.addAccountExplicitly(newAccount, (password != null) ? password : "", null);
// copy base URL
accountMgr.setUserData(newAccount, Constants.KEY_OC_BASE_URL, serverUrl);
// copy server version
accountMgr.setUserData(
newAccount,
Constants.KEY_OC_VERSION,
accountMgr.getUserData(account, Constants.KEY_OC_VERSION)
);
// copy cookies
accountMgr.setUserData(
newAccount,
Constants.KEY_COOKIES,
accountMgr.getUserData(account, Constants.KEY_COOKIES)
);
// copy type of authentication
final String isSamlStr = accountMgr.getUserData(account, Constants.KEY_SUPPORTS_SAML_WEB_SSO);
if (Boolean.parseBoolean(isSamlStr)) {
accountMgr.setUserData(newAccount, Constants.KEY_SUPPORTS_SAML_WEB_SSO, "TRUE");
}
final String isOauthStr = accountMgr.getUserData(account, Constants.KEY_SUPPORTS_OAUTH2);
if (Boolean.parseBoolean(isOauthStr)) {
accountMgr.setUserData(newAccount, Constants.KEY_SUPPORTS_OAUTH2, "TRUE");
}
/* TODO - study if it's possible to run this method in a background thread to copy the authToken
if (isOAuth || isSaml) {
accountMgr.setAuthToken(newAccount, mAuthTokenType, mAuthToken);
}
*/
// don't forget the account saved in preferences as the current one
if (currentAccount.name.equals(account.name)) {
AccountUtils.setCurrentOwnCloudAccount(context, newAccountName);
}
// remove the old account
accountMgr.removeAccount(account, null, null);
// will assume it succeeds, not a big deal otherwise
return newAccount;
}
/**
* Checks if an account owns the file (file's ownerId is the same as account name)
* @param file File to check

View File

@ -3,7 +3,9 @@
*
* @author Tobias Kaminsky
* @author David A. Velasco
* @author Chris Narkiewicz
* Copyright (C) 2015 ownCloud Inc.
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
@ -906,7 +908,7 @@ public final class ThumbnailsCacheManager {
String newImageKey = "a_" + mUserId + "_" + mServerName + "_" + newETag;
addBitmapToCache(newImageKey, avatar);
} else {
return TextDrawable.createAvatar(mAccount.name, mAvatarRadius);
return TextDrawable.createAvatar(mAccount, mAvatarRadius);
}
break;
@ -923,7 +925,7 @@ public final class ThumbnailsCacheManager {
}
} catch (Exception e) {
try {
return TextDrawable.createAvatar(mAccount.name, mAvatarRadius);
return TextDrawable.createAvatar(mAccount, mAvatarRadius);
} catch (Exception e1) {
Log_OC.e(TAG, "Error generating fallback avatar");
}
@ -936,7 +938,7 @@ public final class ThumbnailsCacheManager {
if (avatar == null) {
try {
return TextDrawable.createAvatar(mAccount.name, mAvatarRadius);
return TextDrawable.createAvatar(mAccount, mAvatarRadius);
} catch (Exception e1) {
return mResources.getDrawable(R.drawable.ic_user);
}

View File

@ -2,9 +2,11 @@
* ownCloud Android client application
*
* @author David A. Velasco
* @author Chris Narkiewicz
* Copyright (C) 2012 Bartek Przybylski
* Copyright (C) 2015 ownCloud Inc.
* Copyright (C) 2017 Mario Danic
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
@ -25,9 +27,14 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.nextcloud.client.account.UserAccountManager;
import com.owncloud.android.MainApp;
import com.owncloud.android.lib.common.utils.Log_OC;
import javax.inject.Inject;
import dagger.android.AndroidInjection;
/**
* App-registered receiver catching the broadcast intent reporting that the system was
@ -37,6 +44,9 @@ public class BootupBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = BootupBroadcastReceiver.class.getSimpleName();
@Inject
UserAccountManager accountManager;
/**
* Receives broadcast intent reporting that the system was just boot up.
**
@ -45,9 +55,11 @@ public class BootupBroadcastReceiver extends BroadcastReceiver {
*/
@Override
public void onReceive(Context context, Intent intent) {
AndroidInjection.inject(this, context);
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
MainApp.initSyncOperations();
MainApp.initContactsBackup();
MainApp.initSyncOperations(accountManager);
MainApp.initContactsBackup(accountManager);
} else {
Log_OC.d(TAG, "Getting wrong intent: " + intent.getAction());
}

View File

@ -2,8 +2,10 @@
* Nextcloud Android client application
*
* @author Mario Danic
* @author Chris Narkiewicz
* Copyright (C) 2017 Mario Danic
* Copyright (C) 2017 Nextcloud
* Copyright (C) 2919 Chris Narkiewicz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
@ -31,7 +33,8 @@ import android.text.TextUtils;
import com.evernote.android.job.Job;
import com.evernote.android.job.util.support.PersistableBundleCompat;
import com.nextcloud.client.preferences.AppPreferencesImpl;
import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.client.preferences.AppPreferences;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.authentication.AccountUtils;
@ -72,6 +75,14 @@ public class FilesSyncJob extends Job {
public static final String OVERRIDE_POWER_SAVING = "overridePowerSaving";
private static final String WAKELOCK_TAG_SEPARATION = ":";
private UserAccountManager userAccountManager;
private AppPreferences preferences;
public FilesSyncJob(UserAccountManager userAccountManager, AppPreferences preferences) {
this.userAccountManager = userAccountManager;
this.preferences = preferences;
}
@NonNull
@Override
protected Result onRunJob(@NonNull Params params) {
@ -98,14 +109,14 @@ public class FilesSyncJob extends Job {
boolean lightVersion = resources.getBoolean(R.bool.syncedFolder_light);
final boolean skipCustom = bundle.getBoolean(SKIP_CUSTOM, false);
FilesSyncHelper.restartJobsIfNeeded();
FilesSyncHelper.insertAllDBEntries(skipCustom);
FilesSyncHelper.restartJobsIfNeeded(userAccountManager);
FilesSyncHelper.insertAllDBEntries(preferences, skipCustom);
// Create all the providers we'll need
final ContentResolver contentResolver = context.getContentResolver();
final FilesystemDataProvider filesystemDataProvider = new FilesystemDataProvider(contentResolver);
SyncedFolderProvider syncedFolderProvider = new SyncedFolderProvider(contentResolver,
AppPreferencesImpl.fromContext(context));
preferences);
Locale currentLocale = context.getResources().getConfiguration().locale;
SimpleDateFormat sFormatter = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss", currentLocale);

View File

@ -3,8 +3,10 @@
*
* @author Mario Danic
* @author Andy Scherzinger
* @author Chris Narkiewicz
* Copyright (C) 2018 Mario Danic
* Copyright (C) 2018 Andy Scherzinger
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
@ -36,10 +38,10 @@ import android.text.TextUtils;
import com.evernote.android.job.Job;
import com.google.gson.Gson;
import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.client.preferences.AppPreferences;
import com.nextcloud.client.preferences.AppPreferencesImpl;
import com.owncloud.android.R;
import com.owncloud.android.authentication.AccountUtils;
import com.owncloud.android.datamodel.ArbitraryDataProvider;
import com.owncloud.android.datamodel.MediaFolder;
import com.owncloud.android.datamodel.MediaFoldersModel;
@ -72,8 +74,13 @@ public class MediaFoldersDetectionJob extends Job {
private static final String DISABLE_DETECTION_CLICK = "DISABLE_DETECTION_CLICK";
private UserAccountManager userAccountManager;
private Random randomId = new Random();
MediaFoldersDetectionJob(UserAccountManager accountManager) {
this.userAccountManager = accountManager;
}
@NonNull
@Override
protected Result onRunJob(@NonNull Params params) {
@ -114,7 +121,7 @@ public class MediaFoldersDetectionJob extends Job {
videoMediaFolderPaths.removeAll(mediaFoldersModel.getVideoMediaFolders());
if (!imageMediaFolderPaths.isEmpty() || !videoMediaFolderPaths.isEmpty()) {
Account[] accounts = AccountUtils.getAccounts(getContext());
Account[] accounts = userAccountManager.getAccounts();
List<Account> accountList = new ArrayList<>();
for (Account account : accounts) {
if (!arbitraryDataProvider.getBooleanValue(account, ManageAccountsActivity.PENDING_FOR_REMOVAL)) {

View File

@ -2,8 +2,10 @@
* Nextcloud Android client application
*
* @author Mario Danic
* @author Chris Narkiewicz
* Copyright (C) 2017 Mario Danic
* Copyright (C) 2017 Nextcloud GmbH
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
* <p>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@ -20,16 +22,33 @@
*/
package com.owncloud.android.jobs;
import android.content.Context;
import com.evernote.android.job.Job;
import com.evernote.android.job.JobCreator;
import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.client.preferences.AppPreferences;
import androidx.annotation.NonNull;
/**
* Job creator for android-job
*/
public class NCJobCreator implements JobCreator {
private final Context context;
private final UserAccountManager accountManager;
private final AppPreferences preferences;
public NCJobCreator(Context context, UserAccountManager accountManager, AppPreferences preferences) {
this.context = context;
this.accountManager = accountManager;
this.preferences = preferences;
}
@Override
public Job create(String tag) {
public Job create(@NonNull String tag) {
switch (tag) {
case ContactsBackupJob.TAG:
return new ContactsBackupJob();
@ -38,13 +57,13 @@ public class NCJobCreator implements JobCreator {
case AccountRemovalJob.TAG:
return new AccountRemovalJob();
case FilesSyncJob.TAG:
return new FilesSyncJob();
return new FilesSyncJob(accountManager, preferences);
case OfflineSyncJob.TAG:
return new OfflineSyncJob();
return new OfflineSyncJob(accountManager);
case NotificationJob.TAG:
return new NotificationJob();
return new NotificationJob(context, accountManager);
case MediaFoldersDetectionJob.TAG:
return new MediaFoldersDetectionJob();
return new MediaFoldersDetectionJob(accountManager);
default:
return null;
}

View File

@ -2,7 +2,9 @@
* Nextcloud application
*
* @author Mario Danic
* @author Chris Narkiewicz
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* 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
@ -38,6 +40,7 @@ import android.util.Log;
import com.evernote.android.job.Job;
import com.evernote.android.job.util.support.PersistableBundleCompat;
import com.google.gson.Gson;
import com.nextcloud.client.account.UserAccountManager;
import com.owncloud.android.R;
import com.owncloud.android.authentication.AccountUtils;
import com.owncloud.android.datamodel.DecryptedPushMessage;
@ -92,6 +95,12 @@ public class NotificationJob extends Job {
private SecureRandom randomId = new SecureRandom();
private Context context;
private UserAccountManager accountManager;
public NotificationJob(final Context context, final UserAccountManager accountManager) {
this.context = context;
this.accountManager = accountManager;
}
@NonNull
@Override
@ -109,6 +118,7 @@ public class NotificationJob extends Job {
try {
SignatureVerification signatureVerification = PushUtils.verifySignature(context,
accountManager,
base64DecodedSignature,
base64DecodedSubject);

View File

@ -2,7 +2,9 @@
* Nextcloud Android client application
*
* @author Mario Danic
* @author Chris Narkiewicz
* Copyright (C) 2018 Mario Danic
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
@ -28,6 +30,7 @@ import com.evernote.android.job.Job;
import com.evernote.android.job.JobManager;
import com.evernote.android.job.JobRequest;
import com.evernote.android.job.util.Device;
import com.nextcloud.client.account.UserAccountManager;
import com.owncloud.android.MainApp;
import com.owncloud.android.authentication.AccountUtils;
import com.owncloud.android.datamodel.FileDataStorageManager;
@ -49,6 +52,11 @@ public class OfflineSyncJob extends Job {
public static final String TAG = "OfflineSyncJob";
private static final String WAKELOCK_TAG_SEPARATION = ":";
private UserAccountManager userAccountManager;
public OfflineSyncJob(UserAccountManager userAccountManager) {
this.userAccountManager = userAccountManager;
}
@NonNull
@Override
@ -76,7 +84,7 @@ public class OfflineSyncJob extends Job {
}
}
Account[] accounts = AccountUtils.getAccounts(context);
Account[] accounts = userAccountManager.getAccounts();
for (Account account : accounts) {
FileDataStorageManager storageManager = new FileDataStorageManager(account,

View File

@ -2,7 +2,9 @@
* Nextcloud Android client application
*
* @author Bartosz Przybylski
* @author Chris Narkiewicz
* Copyright (C) 2016 Bartosz Przybylski <bart.p.pl@gmail.com>
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
@ -43,6 +45,7 @@ import android.widget.Toast;
import com.evernote.android.job.JobRequest;
import com.evernote.android.job.util.Device;
import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.client.preferences.AppPreferences;
import com.nextcloud.client.preferences.AppPreferencesImpl;
import com.owncloud.android.MainApp;
@ -82,6 +85,10 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import dagger.android.AndroidInjection;
@TargetApi(Build.VERSION_CODES.KITKAT)
public class DocumentsStorageProvider extends DocumentsProvider {
@ -91,6 +98,10 @@ public class DocumentsStorageProvider extends DocumentsProvider {
private Map<Long, FileDataStorageManager> rootIdToStorageManager;
private OwnCloudClient client;
@Inject UserAccountManager accountManager;
@Override
public Cursor queryRoots(String[] projection) throws FileNotFoundException {
Context context = MainApp.getAppContext();
@ -104,7 +115,7 @@ public class DocumentsStorageProvider extends DocumentsProvider {
final RootCursor result = new RootCursor(projection);
for (Account account : AccountUtils.getAccounts(getContext())) {
for (Account account : accountManager.getAccounts()) {
result.addRoot(account, getContext());
}
@ -288,6 +299,7 @@ public class DocumentsStorageProvider extends DocumentsProvider {
@Override
public boolean onCreate() {
AndroidInjection.inject(this);
return true;
}
@ -587,7 +599,7 @@ public class DocumentsStorageProvider extends DocumentsProvider {
ContentResolver contentResolver = context.getContentResolver();
for (Account account : AccountUtils.getAccounts(getContext())) {
for (Account account : accountManager.getAccounts()) {
final FileDataStorageManager storageManager = new FileDataStorageManager(account, contentResolver);
final OCFile rootDir = storageManager.getFileByPath("/");
rootIdToStorageManager.put(rootDir.getFileId(), storageManager);

View File

@ -3,8 +3,10 @@
*
* @author Andy Scherzinger
* @author Tobias Kaminsiky
* @author Chris Narkiewicz
* Copyright (C) 2016 ownCloud Inc.
* Copyright (C) 2018 Andy Scherzinger
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
@ -21,6 +23,7 @@
package com.owncloud.android.ui;
import android.accounts.Account;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
@ -28,6 +31,7 @@ import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import com.nextcloud.client.account.UserAccountManager;
import com.owncloud.android.authentication.AccountUtils;
import com.owncloud.android.utils.BitmapUtils;
import com.owncloud.android.utils.NextcloudServer;
@ -91,7 +95,7 @@ public class TextDrawable extends Drawable {
* creates an avatar in form of a TextDrawable with the first letter of the account name in a circle with the
* given radius.
*
* @param accountName the account name
* @param account user account
* @param radiusInDp the circle's radius
* @return the avatar as a TextDrawable
* @throws UnsupportedEncodingException if the charset is not supported when calculating the color values
@ -99,9 +103,9 @@ public class TextDrawable extends Drawable {
*/
@NonNull
@NextcloudServer(max = 12)
public static TextDrawable createAvatar(String accountName, float radiusInDp) throws
public static TextDrawable createAvatar(Account account, float radiusInDp) throws
NoSuchAlgorithmException {
String username = AccountUtils.getAccountUsername(accountName);
String username = UserAccountManager.getUsername(account);
return createNamedAvatar(username, radiusInDp);
}

View File

@ -3,10 +3,12 @@
*
* @author Andy Scherzinger
* @author Tobias Kaminsky
* @author Chris Narkiewicz
* Copyright (C) 2016 Andy Scherzinger
* Copyright (C) 2017 Tobias Kaminsky
* Copyright (C) 2016 Nextcloud
* Copyright (C) 2016 ownCloud Inc.
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
@ -54,6 +56,7 @@ import com.bumptech.glide.Glide;
import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.SimpleTarget;
import com.google.android.material.navigation.NavigationView;
import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.client.di.Injectable;
import com.nextcloud.client.preferences.AppPreferences;
import com.owncloud.android.MainApp;
@ -704,7 +707,7 @@ public abstract class DrawerActivity extends ToolbarActivity
Menu.NONE,
MENU_ORDER_ACCOUNT,
account.name)
.setIcon(TextDrawable.createAvatar(account.name, mMenuAccountAvatarRadiusDimension));
.setIcon(TextDrawable.createAvatar(account, mMenuAccountAvatarRadiusDimension));
DisplayUtils.setAvatar(account, this, mMenuAccountAvatarRadiusDimension, getResources(),
accountMenuItem, this);
}
@ -771,7 +774,7 @@ public abstract class DrawerActivity extends ToolbarActivity
username.setTextColor(ThemeUtils.fontColor(this));
} catch (com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException e) {
Log_OC.w(TAG, "Couldn't read display name of account fallback to account name");
username.setText(AccountUtils.getAccountUsername(account.name));
username.setText(UserAccountManager.getUsername(account));
}
View currentAccountView = findNavigationViewChildById(R.id.drawer_current_account);

View File

@ -2,8 +2,10 @@
* ownCloud Android client application
*
* @author David A. Velasco
* @author Chris Narkiewicz
* Copyright (C) 2011 Bartek Przybylski
* Copyright (C) 2016 ownCloud Inc.
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
@ -37,6 +39,7 @@ import android.os.IBinder;
import android.view.View;
import com.google.android.material.snackbar.Snackbar;
import com.nextcloud.client.account.UserAccountManager;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.authentication.AccountUtils;
@ -78,6 +81,8 @@ import com.owncloud.android.utils.ErrorMessageAdapter;
import com.owncloud.android.utils.FilesSyncHelper;
import com.owncloud.android.utils.ThemeUtils;
import javax.inject.Inject;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
@ -136,7 +141,7 @@ public abstract class FileActivity extends DrawerActivity
private ServiceConnection mDownloadServiceConnection;
private ServiceConnection mUploadServiceConnection;
@Inject UserAccountManager accountManager;
@Override
public void showFiles(boolean onDeviceOnly) {
@ -174,7 +179,7 @@ public abstract class FileActivity extends DrawerActivity
Thread t = new Thread(() -> {
// best place, before any access to AccountManager or database
AccountUtils.updateAccountVersion(this);
accountManager.updateAccountVersion();
});
t.start();

View File

@ -4,9 +4,11 @@
* @author Bartek Przybylski
* @author David A. Velasco
* @author Andy Scherzinger
* @author Chris Narkiewicz
* Copyright (C) 2011 Bartek Przybylski
* Copyright (C) 2016 ownCloud Inc.
* Copyright (C) 2018 Andy Scherzinger
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
@ -56,6 +58,7 @@ import android.widget.ImageView;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.snackbar.Snackbar;
import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.client.di.Injectable;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
@ -210,8 +213,8 @@ public class FileDisplayActivity extends FileActivity
private boolean searchOpen;
private SearchView searchView;
@Inject
AppPreferences preferences;
@Inject AppPreferences preferences;
@Inject UserAccountManager accountManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -2567,9 +2570,9 @@ public class FileDisplayActivity extends FileActivity
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMessageEvent(TokenPushEvent event) {
if (!preferences.isKeysReInitEnabled()) {
PushUtils.reinitKeys();
PushUtils.reinitKeys(accountManager);
} else {
PushUtils.pushRegistrationToServer(preferences.getPushToken());
PushUtils.pushRegistrationToServer(accountManager, preferences.getPushToken());
}
}

View File

@ -2,9 +2,11 @@
* Nextcloud Android client application
*
* @author Bartosz Przybylski
* @author Chris Narkiewicz
* Copyright (C) 2015 Bartosz Przybylski
* Copyright (C) 2015 ownCloud Inc.
* Copyright (C) 2016 Nextcloud.
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
@ -37,6 +39,7 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.viewpager.widget.ViewPager;
import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.client.di.Injectable;
import com.nextcloud.client.preferences.AppPreferences;
import com.owncloud.android.MainApp;
@ -60,6 +63,8 @@ public class FirstRunActivity extends BaseActivity implements ViewPager.OnPageCh
public static final int FIRST_RUN_RESULT_CODE = 199;
private ProgressIndicator progressIndicator;
@Inject UserAccountManager userAccountManager;
@Inject AppPreferences preferences;
@Override
@ -112,7 +117,7 @@ public class FirstRunActivity extends BaseActivity implements ViewPager.OnPageCh
if (isFirstRun(this)) {
AccountManager am = (AccountManager) getSystemService(ACCOUNT_SERVICE);
if (am != null) {
for (Account account : AccountUtils.getAccounts(this)) {
for (Account account : userAccountManager.getAccounts()) {
am.removeAccount(account, null, null);
}
}

View File

@ -3,9 +3,11 @@
*
* @author Bartek Przybylski
* @author David A. Velasco
* @author Chris Narkiewicz
* Copyright (C) 2011 Bartek Przybylski
* Copyright (C) 2016 ownCloud Inc.
* Copyright (C) 2016 Nextcloud
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
@ -55,6 +57,7 @@ import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.core.content.res.ResourcesCompat;
import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.client.di.Injectable;
import com.nextcloud.client.preferences.AppPreferences;
import com.nextcloud.client.preferences.AppPreferencesImpl;
@ -751,7 +754,7 @@ public class SettingsActivity extends PreferenceActivity
if (serverBaseUri != null) {
davDroidLoginIntent.putExtra("url", serverBaseUri.toString() + DAV_PATH);
}
davDroidLoginIntent.putExtra("username", AccountUtils.getAccountUsername(account.name));
davDroidLoginIntent.putExtra("username", UserAccountManager.getUsername(account));
startActivityForResult(davDroidLoginIntent, ACTION_REQUEST_CODE_DAVDROID_SETUP);
} else {
// DAVdroid not installed

View File

@ -2,8 +2,10 @@
* Nextcloud Android client application
*
* @author Tobias Kaminsky
* @author Chris Narkiewicz
* Copyright (C) 2018 Tobias Kaminsky
* Copyright (C) 2018 Nextcloud
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
@ -42,6 +44,7 @@ import com.evernote.android.job.JobManager;
import com.evernote.android.job.JobRequest;
import com.evernote.android.job.util.support.PersistableBundleCompat;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.nextcloud.client.account.UserAccountManager;
import com.owncloud.android.R;
import com.owncloud.android.datamodel.UploadsStorageManager;
import com.owncloud.android.files.services.FileUploader;
@ -60,6 +63,8 @@ import com.owncloud.android.utils.ThemeUtils;
import java.util.Set;
import javax.inject.Inject;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import butterknife.BindString;
@ -103,6 +108,7 @@ public class UploadListActivity extends FileActivity {
public String noResultsMessage;
private Unbinder unbinder;
@Inject UserAccountManager userAccountManager;
@Override
public void showFiles(boolean onDeviceOnly) {
@ -275,7 +281,7 @@ public class UploadListActivity extends FileActivity {
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == FileActivity.REQUEST_CODE__UPDATE_CREDENTIALS && resultCode == RESULT_OK) {
FilesSyncHelper.restartJobsIfNeeded();
FilesSyncHelper.restartJobsIfNeeded(userAccountManager);
}
}
@ -295,7 +301,7 @@ public class UploadListActivity extends FileActivity {
} else {
// already updated -> just retry!
FilesSyncHelper.restartJobsIfNeeded();
FilesSyncHelper.restartJobsIfNeeded(userAccountManager);
}
} else {

View File

@ -3,9 +3,11 @@
*
* @author Mario Danic
* @author Andy Scherzinger
* @author Chris Narkiewicz
* Copyright (C) 2017 Mario Danic
* Copyright (C) 2017 Andy Scherzinger
* Copyright (C) 2017 Nextcloud GmbH.
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@ -51,6 +53,7 @@ import com.bumptech.glide.Glide;
import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.SimpleTarget;
import com.google.gson.Gson;
import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.client.di.Injectable;
import com.nextcloud.client.preferences.AppPreferences;
import com.owncloud.android.R;
@ -117,6 +120,7 @@ public class UserInfoActivity extends FileActivity implements Injectable {
@BindString(R.string.user_information_retrieval_error) protected String sorryMessage;
@Inject AppPreferences preferences;
@Inject UserAccountManager accountManager;
private float mCurrentAccountAvatarRadiusDimension;
private Unbinder unbinder;
@ -443,7 +447,7 @@ public class UserInfoActivity extends FileActivity implements Injectable {
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMessageEvent(TokenPushEvent event) {
PushUtils.pushRegistrationToServer(preferences.getPushToken());
PushUtils.pushRegistrationToServer(accountManager, preferences.getPushToken());
}

View File

@ -2,7 +2,9 @@
* ownCloud Android client application
*
* @author Andy Scherzinger
* @author Chris Narkiewicz
* Copyright (C) 2016 ownCloud Inc.
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
* <p/>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
@ -29,6 +31,7 @@ import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.nextcloud.client.account.UserAccountManager;
import com.owncloud.android.R;
import com.owncloud.android.authentication.AccountUtils;
import com.owncloud.android.lib.common.OwnCloudAccount;
@ -173,7 +176,7 @@ public class AccountListAdapter extends ArrayAdapter<AccountListItem> implements
viewHolder.usernameViewItem.setText(oca.getDisplayName());
} catch (Exception e) {
Log_OC.w(TAG, "Account not found right after being read; using account name instead");
viewHolder.usernameViewItem.setText(AccountUtils.getAccountUsername(account.name));
viewHolder.usernameViewItem.setText(UserAccountManager.getUsername(account));
}
viewHolder.usernameViewItem.setTag(account.name);
}

View File

@ -2,8 +2,10 @@
* Nextcloud Android client application
*
* @author Mario Danic
* @author Chris Narkiewicz
* Copyright (C) 2017 Mario Danic
* Copyright (C) 2017 Nextcloud
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
@ -36,9 +38,9 @@ import android.util.Log;
import com.evernote.android.job.JobManager;
import com.evernote.android.job.JobRequest;
import com.evernote.android.job.util.Device;
import com.nextcloud.client.preferences.AppPreferencesImpl;
import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.client.preferences.AppPreferences;
import com.owncloud.android.MainApp;
import com.owncloud.android.authentication.AccountUtils;
import com.owncloud.android.datamodel.ArbitraryDataProvider;
import com.owncloud.android.datamodel.FilesystemDataProvider;
import com.owncloud.android.datamodel.MediaFolderType;
@ -155,11 +157,11 @@ public final class FilesSyncHelper {
}
}
public static void insertAllDBEntries(boolean skipCustom) {
public static void insertAllDBEntries(AppPreferences preferences, boolean skipCustom) {
final Context context = MainApp.getAppContext();
final ContentResolver contentResolver = context.getContentResolver();
SyncedFolderProvider syncedFolderProvider = new SyncedFolderProvider(contentResolver,
AppPreferencesImpl.fromContext(context));
preferences);
for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) {
if (syncedFolder.isEnabled() && (MediaFolderType.CUSTOM != syncedFolder.getType() || !skipCustom)) {
@ -212,7 +214,7 @@ public final class FilesSyncHelper {
}
}
public static void restartJobsIfNeeded() {
public static void restartJobsIfNeeded(UserAccountManager accountManager) {
final Context context = MainApp.getAppContext();
FileUploader.UploadRequester uploadRequester = new FileUploader.UploadRequester();
@ -226,7 +228,7 @@ public final class FilesSyncHelper {
accountExists = false;
// check if accounts still exists
for (Account account : AccountUtils.getAccounts(context)) {
for (Account account : accountManager.getAccounts()) {
if (account.name.equals(failedUpload.getAccountName())) {
accountExists = true;
break;

View File

@ -1,9 +1,11 @@
/**
/*
* Nextcloud Android client application
*
* @author Mario Danic
* @author Chris Narkiewicz
* Copyright (C) 2017 Mario Danic
* Copyright (C) 2017 Nextcloud
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
@ -27,6 +29,7 @@ import android.content.IntentFilter;
import com.evernote.android.job.JobRequest;
import com.evernote.android.job.util.Device;
import com.nextcloud.client.account.UserAccountManager;
import com.owncloud.android.MainApp;
/**
@ -38,7 +41,7 @@ public final class ReceiversHelper {
// utility class -> private constructor
}
public static void registerNetworkChangeReceiver() {
public static void registerNetworkChangeReceiver(final UserAccountManager accountManager) {
Context context = MainApp.getAppContext();
IntentFilter intentFilter = new IntentFilter();
@ -49,7 +52,7 @@ public final class ReceiversHelper {
@Override
public void onReceive(Context context, Intent intent) {
if (!Device.getNetworkType(context).equals(JobRequest.NetworkType.ANY)) {
FilesSyncHelper.restartJobsIfNeeded();
FilesSyncHelper.restartJobsIfNeeded(accountManager);
}
}
};
@ -57,7 +60,7 @@ public final class ReceiversHelper {
context.registerReceiver(broadcastReceiver, intentFilter);
}
public static void registerPowerChangeReceiver() {
public static void registerPowerChangeReceiver(final UserAccountManager accountManager) {
Context context = MainApp.getAppContext();
IntentFilter intentFilter = new IntentFilter();
@ -68,7 +71,7 @@ public final class ReceiversHelper {
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_POWER_CONNECTED.equals(intent.getAction())) {
FilesSyncHelper.restartJobsIfNeeded();
FilesSyncHelper.restartJobsIfNeeded(accountManager);
}
}
};
@ -76,7 +79,7 @@ public final class ReceiversHelper {
context.registerReceiver(broadcastReceiver, intentFilter);
}
public static void registerPowerSaveReceiver() {
public static void registerPowerSaveReceiver(final UserAccountManager accountManager) {
Context context = MainApp.getAppContext();
IntentFilter intentFilter = new IntentFilter();
@ -86,7 +89,7 @@ public final class ReceiversHelper {
@Override
public void onReceive(Context context, Intent intent) {
if (!PowerUtils.isPowerSaveMode(context)) {
FilesSyncHelper.restartJobsIfNeeded();
FilesSyncHelper.restartJobsIfNeeded(accountManager);
}
}
};

View File

@ -0,0 +1,26 @@
/*
* Nextcloud Android client application
*
* @author Chris Narkiewicz
* Copyright (C) 2919 Chris Narkiewicz <hello@ezaquarii.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or 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 AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.nextcloud.client.di;
import dagger.Module;
@Module
abstract class VariantComponentsModule {
}

View File

@ -2,7 +2,9 @@
* Nextcloud Android client application
*
* @author Mario Danic
* @author Chris Narkiewicz
* Copyright (C) 2017 Mario Danic
* Copyright (C) 2019 Chris Narkiewicz
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@ -22,6 +24,7 @@ package com.owncloud.android.utils;
import android.content.Context;
import com.nextcloud.client.account.UserAccountManager;
import com.owncloud.android.MainApp;
import com.owncloud.android.datamodel.SignatureVerification;
import com.nextcloud.client.preferences.AppPreferencesImpl;
@ -34,11 +37,14 @@ public final class PushUtils {
private PushUtils() {
}
public static void pushRegistrationToServer(final String pushToken) {
public static void pushRegistrationToServer(
final UserAccountManager accountManager,
final String pushToken)
{
// do nothing
}
public static void reinitKeys() {
public static void reinitKeys(final UserAccountManager accountManager) {
Context context = MainApp.getAppContext();
AppPreferencesImpl.fromContext(context).setKeysReInitEnabled();
}
@ -47,7 +53,11 @@ public final class PushUtils {
return null;
}
public static SignatureVerification verifySignature(Context context, byte[] signatureBytes, byte[] subjectBytes) {
public static SignatureVerification verifySignature(
final Context context,
final UserAccountManager accountManager,
final byte[] signatureBytes, final byte[] subjectBytes
) {
return null;
}
}