I am building an App that relies heavily on users in parse.com. I have a problem when logging out and then logging in again, all requests get "invalid session exception".
If I kill the App and tries again, everything works ok (I don't need to re-log, it just works as soon as I restart the app).
All my parse queries are done via a Sync adapter and a sync service.
I tried stopping the service, clearing cookies cache and everything I could think of. I'm not sure if it's an issue with parse.com or with the android's sync adapter / sync service.
Can anyone shed light on how to force Android (or parse) to flush the session token?
Login:
@Override
public void onLoginClicked(final String email, String password) {
ProgressDialog progress = new ProgressDialog(this);
progress.setMessage(getString(R.string.logging_in));
progress.show();
try {
ParseUser.logIn(email,password);
ParseUser me = ParseUser.getCurrentUser();
if (me != null) {
DoUIParseSyncAdapter.updateInstallation();
if (me.getString(DoUIParseSyncAdapter.PARTNER_ID) != null) {
goToMainScreen();
}
else {
showConnectToPartnerScreen(email);
}
}
else {
Toast.makeText(this,R.string.login_failed,Toast.LENGTH_LONG).show();
}
} catch (ParseException e) {
Toast.makeText(this,e.getMessage(),Toast.LENGTH_LONG).show();
e.printStackTrace();
}
finally {
progress.dismiss();
}
}
Logout:
public static void logout(final Context context) {
ParseUser.logOutInBackground(new LogOutCallback() {
@Override
public void done(ParseException e) {
if (e != null) {
e.printStackTrace();
}
DbHelper helper = new DbHelper(context);
helper.onUpgrade(helper.getWritableDatabase(), 0, 0);
DoUISyncAdapter.removeSyncAccount(context);
context.stopService(new Intent(context.getApplicationContext(),DoUISyncService.class));
CookieManager manager = CookieManager.getInstance();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
manager.removeAllCookies(new ValueCallback<Boolean>() {
@Override
public void onReceiveValue(Boolean aBoolean) {
}
});
}
else {
manager.removeAllCookie();
}
}
});
}
SyncAdapter:
public class DoUISyncAdapter extends AbstractThreadedSyncAdapter {
private static final String LOG_TAG = DoUISyncAdapter.class.getSimpleName();
public static final int SYNC_INTERVAL = 60 * 180;
public static final int SYNC_FLEXTIME = SYNC_INTERVAL/3;
public DoUISyncAdapter(Context context, boolean autoInitialize) {
super(context, autoInitialize);
}
@Override
public void onPerformSync(Account account, Bundle bundle, String s, ContentProviderClient contentProviderClient, SyncResult syncResult) {
String table = bundle.getString("requestedTable");
if (table == null) {
DoUIParseSyncAdapter.getInstance().syncTasks(getContext());
//DoUIParseSyncAdapter.getInstance().syncGeneralItems(getContext());
DoUIParseSyncAdapter.getInstance().syncShoppingItems(getContext());
}
else {
if (table.equals(DoUIContract.PATH_TASKS)) {
DoUIParseSyncAdapter.getInstance().syncTasks(getContext());
}
else if (table.equals(DoUIContract.PATH_SHOPPING)) {
DoUIParseSyncAdapter.getInstance().syncShoppingItems(getContext());
}
}
}
public static void initializeSyncAdapter(Context context) {
getSyncAccount(context);
}
public static void syncImmediately(Context context,String table) {
Bundle bundle = new Bundle();
bundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
bundle.putString("requestedTable",table);
ContentResolver.requestSync(getSyncAccount(context),
context.getString(R.string.content_authority), bundle);
}
public static Account getSyncAccount(Context context) {
// Get an instance of the Android account manager
AccountManager accountManager =
(AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE);
// Create the account type and default account
Account newAccount = new Account(
context.getString(R.string.app_name), context.getString(R.string.sync_account_type));
// If the password doesn't exist, the account doesn't exist
if ( null == accountManager.getPassword(newAccount) ) {
/*
* Add the account and account type, no password or user data
* If successful, return the Account object, otherwise report an error.
*/
if (!accountManager.addAccountExplicitly(newAccount, "", null)) {
return null;
}
/*
* If you don't set android:syncable="true" in
* in your <provider> element in the manifest,
* then call ContentResolver.setIsSyncable(account, AUTHORITY, 1)
* here.
*/
}
return newAccount;
}
public static void configurePeriodicSync(Context context, int syncInterval, int flexTime) {
Account account = getSyncAccount(context);
String authority = context.getString(R.string.content_authority);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// we can enable inexact timers in our periodic sync
SyncRequest request = new SyncRequest.Builder().
syncPeriodic(syncInterval, flexTime).
setSyncAdapter(account, authority).
setExtras(new Bundle()).build();
ContentResolver.requestSync(request);
} else {
ContentResolver.addPeriodicSync(account,
authority, new Bundle(), syncInterval);
}
}
public static void removeSyncAccount(Context context) {
ContentResolver.cancelSync(getSyncAccount(context),context.getString(R.string.content_authority));
ContentResolver.removePeriodicSync(getSyncAccount(context),context.getString(R.string.content_authority),new Bundle());
AccountManager accountManager =
(AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE);
Account[] accounts = accountManager.getAccounts();
for (int index = 0; index < accounts.length; index++) {
if (accounts[index].type.intern() == "com.ymgeva.doui")
accountManager.removeAccount(accounts[index], null, null);
}
}
@Override
public void onSyncCanceled() {
super.onSyncCanceled();
getContext().stopService(new Intent(getContext(),DoUISyncService.class));
}
public static void onAccountCreated(Context context) {
DoUISyncAdapter.configurePeriodicSync(context, SYNC_INTERVAL, SYNC_FLEXTIME);
ContentResolver.setSyncAutomatically(getSyncAccount(context), context.getString(R.string.content_authority), true);
syncImmediately(context,null);
}
}