migrating to native account framework

This commit is contained in:
Mariotaku Lee 2016-12-03 14:41:45 +08:00
parent 2e619006a7
commit b5bbae90d5
7 changed files with 106 additions and 132 deletions

View File

@ -8,7 +8,6 @@ import android.support.annotation.Nullable;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import org.mariotaku.twidere.R; import org.mariotaku.twidere.R;
import org.mariotaku.twidere.TwidereConstants;
import org.mariotaku.twidere.annotation.AccountType; import org.mariotaku.twidere.annotation.AccountType;
import org.mariotaku.twidere.extension.AccountExtensionsKt; import org.mariotaku.twidere.extension.AccountExtensionsKt;
import org.mariotaku.twidere.model.ParcelableAccount; import org.mariotaku.twidere.model.ParcelableAccount;
@ -50,7 +49,7 @@ public class ParcelableAccountUtils {
final boolean officialKeyOnly) { final boolean officialKeyOnly) {
ArrayList<Account> accounts = new ArrayList<>(); ArrayList<Account> accounts = new ArrayList<>();
final AccountManager am = AccountManager.get(context); final AccountManager am = AccountManager.get(context);
for (Account account : am.getAccountsByType(TwidereConstants.ACCOUNT_TYPE)) { for (Account account : AccountUtils.getAccounts(am)) {
boolean activated = AccountExtensionsKt.isAccountActivated(account, am); boolean activated = AccountExtensionsKt.isAccountActivated(account, am);
if (!activated && activatedOnly) continue; if (!activated && activatedOnly) continue;
boolean isOfficialKey = isOfficialKey(context, account, am); boolean isOfficialKey = isOfficialKey(context, account, am);
@ -71,14 +70,14 @@ public class ParcelableAccountUtils {
public static ParcelableAccount[] getAccounts(@NonNull final Context context) { public static ParcelableAccount[] getAccounts(@NonNull final Context context) {
final AccountManager am = AccountManager.get(context); final AccountManager am = AccountManager.get(context);
return getAccounts(am, am.getAccountsByType(TwidereConstants.ACCOUNT_TYPE)); return getAccounts(am, AccountUtils.getAccounts(am));
} }
@NonNull @NonNull
public static ParcelableAccount[] getAccounts(@NonNull final Context context, @NonNull final UserKey... accountIds) { public static ParcelableAccount[] getAccounts(@NonNull final Context context, @NonNull final UserKey... accountIds) {
ArrayList<Account> accounts = new ArrayList<>(); ArrayList<Account> accounts = new ArrayList<>();
final AccountManager am = AccountManager.get(context); final AccountManager am = AccountManager.get(context);
for (Account account : am.getAccountsByType(TwidereConstants.ACCOUNT_TYPE)) { for (Account account : AccountUtils.getAccounts(am)) {
if (ArrayUtils.contains(accountIds, AccountExtensionsKt.getAccountKey(account, am))) { if (ArrayUtils.contains(accountIds, AccountExtensionsKt.getAccountKey(account, am))) {
accounts.add(account); accounts.add(account);
} }
@ -87,7 +86,7 @@ public class ParcelableAccountUtils {
} }
@NonNull @NonNull
public static ParcelableAccount[] getAccounts(@Nullable final AccountManager am, @Nullable final Account[] accounts) { public static ParcelableAccount[] getAccounts(@NonNull final AccountManager am, @Nullable final Account[] accounts) {
if (accounts == null) return new ParcelableAccount[0]; if (accounts == null) return new ParcelableAccount[0];
final ParcelableAccount[] parcelableAccounts = new ParcelableAccount[accounts.length]; final ParcelableAccount[] parcelableAccounts = new ParcelableAccount[accounts.length];
for (int i = 0; i < accounts.length; i++) { for (int i = 0; i < accounts.length; i++) {

View File

@ -1,119 +0,0 @@
package org.mariotaku.twidere.task;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.support.annotation.NonNull;
import android.support.v4.util.LongSparseArray;
import android.text.TextUtils;
import org.mariotaku.abstask.library.AbstractTask;
import org.mariotaku.sqliteqb.library.Expression;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.model.Tab;
import org.mariotaku.twidere.model.TabCursorIndices;
import org.mariotaku.twidere.model.TabValuesCreator;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.tab.argument.TabArguments;
import org.mariotaku.twidere.provider.TwidereDataStore.AccountSupportColumns;
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
import org.mariotaku.twidere.provider.TwidereDataStore.Activities;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedRelationships;
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages;
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
import org.mariotaku.twidere.provider.TwidereDataStore.Tabs;
import org.mariotaku.twidere.util.JsonSerializer;
import java.io.IOException;
import kotlin.Pair;
/**
* Created by mariotaku on 16/3/8.
*/
public class UpdateAccountInfoTask extends AbstractTask<Pair<ParcelableAccount, ParcelableUser>, Object, Object> {
private final Context context;
public UpdateAccountInfoTask(Context context) {
this.context = context;
}
@Override
protected Object doLongOperation(Pair<ParcelableAccount, ParcelableUser> params) {
final ContentResolver resolver = context.getContentResolver();
final ParcelableAccount account = params.getFirst();
final ParcelableUser user = params.getSecond();
if (account == null || user == null) return null;
if (user.is_cache) {
return null;
}
if (!user.key.maybeEquals(user.account_key)) {
return null;
}
final String accountWhere = Expression.equalsArgs(Accounts._ID).getSQL();
final String[] accountWhereArgs = {String.valueOf(account.id)};
final ContentValues accountValues = new ContentValues();
accountValues.put(Accounts.NAME, user.name);
accountValues.put(Accounts.SCREEN_NAME, user.screen_name);
accountValues.put(Accounts.PROFILE_IMAGE_URL, user.profile_image_url);
accountValues.put(Accounts.PROFILE_BANNER_URL, user.profile_banner_url);
accountValues.put(Accounts.ACCOUNT_USER, JsonSerializer.serialize(user,
ParcelableUser.class));
accountValues.put(Accounts.ACCOUNT_KEY, String.valueOf(user.key));
resolver.update(Accounts.CONTENT_URI, accountValues, accountWhere, accountWhereArgs);
final ContentValues accountKeyValues = new ContentValues();
accountKeyValues.put(AccountSupportColumns.ACCOUNT_KEY, String.valueOf(user.key));
final String accountKeyWhere = Expression.equalsArgs(AccountSupportColumns.ACCOUNT_KEY).getSQL();
final String[] accountKeyWhereArgs = {account.account_key.toString()};
resolver.update(Statuses.CONTENT_URI, accountKeyValues, accountKeyWhere, accountKeyWhereArgs);
resolver.update(Activities.AboutMe.CONTENT_URI, accountKeyValues, accountKeyWhere, accountKeyWhereArgs);
resolver.update(DirectMessages.Inbox.CONTENT_URI, accountKeyValues, accountKeyWhere, accountKeyWhereArgs);
resolver.update(DirectMessages.Outbox.CONTENT_URI, accountKeyValues, accountKeyWhere, accountKeyWhereArgs);
resolver.update(CachedRelationships.CONTENT_URI, accountKeyValues, accountKeyWhere, accountKeyWhereArgs);
updateTabs(context, resolver, user.key);
return null;
}
private void updateTabs(@NonNull Context context, @NonNull ContentResolver resolver, UserKey accountKey) {
Cursor tabsCursor = resolver.query(Tabs.CONTENT_URI, Tabs.COLUMNS, null, null, null);
if (tabsCursor == null) return;
try {
TabCursorIndices indices = new TabCursorIndices(tabsCursor);
tabsCursor.moveToFirst();
LongSparseArray<ContentValues> values = new LongSparseArray<>();
while (!tabsCursor.isAfterLast()) {
Tab tab = indices.newObject(tabsCursor);
TabArguments arguments = tab.getArguments();
if (arguments != null) {
final String accountId = arguments.getAccountId();
final UserKey[] keys = arguments.getAccountKeys();
if (TextUtils.equals(accountKey.getId(), accountId) && keys == null) {
arguments.setAccountKeys(new UserKey[]{accountKey});
values.put(tab.getId(), TabValuesCreator.create(tab));
}
}
tabsCursor.moveToNext();
}
final String where = Expression.equalsArgs(Tabs._ID).getSQL();
for (int i = 0, j = values.size(); i < j; i++) {
final String[] whereArgs = {String.valueOf(values.keyAt(i))};
resolver.update(Tabs.CONTENT_URI, values.valueAt(i), where, whereArgs);
}
} catch (IOException e) {
// Ignore
} finally {
tabsCursor.close();
}
}
}

View File

@ -0,0 +1,92 @@
package org.mariotaku.twidere.task
import android.accounts.Account
import android.accounts.AccountManager
import android.content.ContentResolver
import android.content.ContentValues
import android.content.Context
import android.support.v4.util.LongSparseArray
import android.text.TextUtils
import com.bluelinelabs.logansquare.LoganSquare
import org.mariotaku.abstask.library.AbstractTask
import org.mariotaku.sqliteqb.library.Expression
import org.mariotaku.twidere.TwidereConstants
import org.mariotaku.twidere.TwidereConstants.ACCOUNT_USER_DATA_KEY
import org.mariotaku.twidere.TwidereConstants.ACCOUNT_USER_DATA_USER
import org.mariotaku.twidere.extension.model.account_name
import org.mariotaku.twidere.model.*
import org.mariotaku.twidere.provider.TwidereDataStore.*
import java.io.IOException
/**
* Created by mariotaku on 16/3/8.
*/
class UpdateAccountInfoTask(private val context: Context) : AbstractTask<Pair<ParcelableAccount, ParcelableUser>, Any, Any>() {
override fun doLongOperation(params: Pair<ParcelableAccount, ParcelableUser>): Any? {
val resolver = context.contentResolver
val account = params.first
val user = params.second
if (user.is_cache) {
return null
}
if (!user.key.maybeEquals(user.account_key)) {
return null
}
val am = AccountManager.get(context)
val account1 = Account(account.account_name, TwidereConstants.ACCOUNT_TYPE)
am.setUserData(account1, ACCOUNT_USER_DATA_USER, LoganSquare.serialize(user))
am.setUserData(account1, ACCOUNT_USER_DATA_KEY, user.key.toString())
val accountKeyValues = ContentValues()
accountKeyValues.put(AccountSupportColumns.ACCOUNT_KEY, user.key.toString())
val accountKeyWhere = Expression.equalsArgs(AccountSupportColumns.ACCOUNT_KEY).sql
val accountKeyWhereArgs = arrayOf(account.account_key.toString())
resolver.update(Statuses.CONTENT_URI, accountKeyValues, accountKeyWhere, accountKeyWhereArgs)
resolver.update(Activities.AboutMe.CONTENT_URI, accountKeyValues, accountKeyWhere, accountKeyWhereArgs)
resolver.update(DirectMessages.Inbox.CONTENT_URI, accountKeyValues, accountKeyWhere, accountKeyWhereArgs)
resolver.update(DirectMessages.Outbox.CONTENT_URI, accountKeyValues, accountKeyWhere, accountKeyWhereArgs)
resolver.update(CachedRelationships.CONTENT_URI, accountKeyValues, accountKeyWhere, accountKeyWhereArgs)
updateTabs(context, resolver, user.key)
return null
}
private fun updateTabs(context: Context, resolver: ContentResolver, accountKey: UserKey) {
val tabsCursor = resolver.query(Tabs.CONTENT_URI, Tabs.COLUMNS, null, null, null) ?: return
try {
val indices = TabCursorIndices(tabsCursor)
tabsCursor.moveToFirst()
val values = LongSparseArray<ContentValues>()
while (!tabsCursor.isAfterLast) {
val tab = indices.newObject(tabsCursor)
val arguments = tab.arguments
if (arguments != null) {
val accountId = arguments.accountId
val keys = arguments.accountKeys
if (TextUtils.equals(accountKey.id, accountId) && keys == null) {
arguments.accountKeys = arrayOf(accountKey)
values.put(tab.id, TabValuesCreator.create(tab))
}
}
tabsCursor.moveToNext()
}
val where = Expression.equalsArgs(Tabs._ID).sql
var i = 0
val j = values.size()
while (i < j) {
val whereArgs = arrayOf(values.keyAt(i).toString())
resolver.update(Tabs.CONTENT_URI, values.valueAt(i), where, whereArgs)
i++
}
} catch (e: IOException) {
// Ignore
} finally {
tabsCursor.close()
}
}
}

View File

@ -19,6 +19,7 @@
package org.mariotaku.twidere.util.content; package org.mariotaku.twidere.util.content;
import android.accounts.AccountManager;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@ -222,7 +223,7 @@ public final class TwidereSQLiteOpenHelper extends SQLiteOpenHelper implements C
if (oldVersion <= 153) { if (oldVersion <= 153) {
migrateLegacyAccounts(db); migrateLegacyAccounts(db);
if (newVersion > 153) { if (newVersion > 153) {
AccountMigratorKt.migrateAccounts(mContext); AccountMigratorKt.migrateAccounts(AccountManager.get(mContext), db);
db.execSQL(SQLQueryBuilder.dropTable(true, Accounts.TABLE_NAME).getSQL()); db.execSQL(SQLQueryBuilder.dropTable(true, Accounts.TABLE_NAME).getSQL());
} }
} }

View File

@ -395,7 +395,7 @@ class UserProfileEditorFragment : BaseSupportFragment(), OnSizeChangedListener,
val account = result.extras.getParcelable<ParcelableAccount>(EXTRA_ACCOUNT) val account = result.extras.getParcelable<ParcelableAccount>(EXTRA_ACCOUNT)
if (account != null) { if (account != null) {
val task = UpdateAccountInfoTask(activity) val task = UpdateAccountInfoTask(activity)
task.params = Pair(account, result.data) task.params = Pair(account, result.data!!)
TaskStarter.execute(task) TaskStarter.execute(task)
} }
} }

View File

@ -30,7 +30,10 @@ internal fun Account.writeParcelableCredentials(am: AccountManager, credentials:
Credentials.Type.OAUTH2 -> ParcelableCredentials.AuthTypeInt.OAUTH2 Credentials.Type.OAUTH2 -> ParcelableCredentials.AuthTypeInt.OAUTH2
else -> ParcelableCredentials.AuthTypeInt.OAUTH else -> ParcelableCredentials.AuthTypeInt.OAUTH
} }
credentials.account_extras = LoganSquare.serialize(getAccountExtras(am)) val extras = getAccountExtras(am)
if (extras != null) {
credentials.account_extras = LoganSquare.serialize(extras)
}
val creds = getCredentials(am) val creds = getCredentials(am)
credentials.api_url_format = creds.api_url_format credentials.api_url_format = creds.api_url_format

View File

@ -2,7 +2,7 @@ package org.mariotaku.twidere.util
import android.accounts.Account import android.accounts.Account
import android.accounts.AccountManager import android.accounts.AccountManager
import android.content.Context import android.database.sqlite.SQLiteDatabase
import android.os.Bundle import android.os.Bundle
import android.support.annotation.ColorInt import android.support.annotation.ColorInt
import com.bluelinelabs.logansquare.LoganSquare import com.bluelinelabs.logansquare.LoganSquare
@ -23,14 +23,12 @@ import java.util.*
/** /**
* Created by mariotaku on 2016/12/3. * Created by mariotaku on 2016/12/3.
*/ */
fun migrateAccounts(context: Context) { fun migrateAccounts(am: AccountManager, db: SQLiteDatabase) {
val am = AccountManager.get(context)
am.getAccountsByType(ACCOUNT_TYPE).map { account -> am.getAccountsByType(ACCOUNT_TYPE).map { account ->
AccountManagerSupport.removeAccount(am, account, null, null, null) AccountManagerSupport.removeAccount(am, account, null, null, null)
} }
val cur = context.contentResolver.query(Accounts.CONTENT_URI, Accounts.COLUMNS, null, null, null) ?: return val cur = db.query(Accounts.TABLE_NAME, Accounts.COLUMNS, null, null, null, null, null) ?: return
try { try {
val indices = ParcelableCredentialsCursorIndices(cur) val indices = ParcelableCredentialsCursorIndices(cur)
cur.moveToFirst() cur.moveToFirst()