diff --git a/res/values/oauth.xml b/res/values/oauth.xml
index b12b648c7c..66bb225593 100644
--- a/res/values/oauth.xml
+++ b/res/values/oauth.xml
@@ -1,5 +1,7 @@
- https://frko.surfnetlabs.nl/workshop/php-oauth/authorize.php
- https://frko.surfnetlabs.nl/workshop/php-oauth/token.php
+
+ http://owncloud.tuxed.net/oauth/php-oauth/authorize.php
+ http://owncloud.tuxed.net/oauth/php-oauth/token.php
diff --git a/res/values/strings.xml b/res/values/strings.xml
index bc35032e3f..21938f09d5 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -111,6 +111,7 @@
Contacts
Synchronization failed
Synchronization of %1$s could not be completed
+ Invalid credentials for %1$s
Conflicts found
%1$d kept-in-sync files could not be sync\'ed
Kept-in-sync files failed
diff --git a/src/com/owncloud/android/operations/RemoteOperation.java b/src/com/owncloud/android/operations/RemoteOperation.java
index bf635a8da9..06a70f703c 100644
--- a/src/com/owncloud/android/operations/RemoteOperation.java
+++ b/src/com/owncloud/android/operations/RemoteOperation.java
@@ -244,6 +244,7 @@ public abstract class RemoteOperation implements Runnable {
repeat = false;
if (mCallerActivity != null && mAccount != null && mContext != null && !result.isSuccess() && result.getCode() == ResultCode.UNAUTHORIZED) {
+ /// fail due to lack of authorization in an operation performed in foreground
AccountManager am = AccountManager.get(mContext);
Credentials cred = mClient.getCredentials();
if (cred instanceof BearerCredentials) {
@@ -252,7 +253,7 @@ public abstract class RemoteOperation implements Runnable {
am.clearPassword(mAccount);
}
mClient = null;
- repeat = true;
+ repeat = true; // when repeated, the creation of a new OwnCloudClient after erasing the saved credentials will trigger the login activity
result = null;
}
} while (repeat);
diff --git a/src/com/owncloud/android/syncadapter/FileSyncAdapter.java b/src/com/owncloud/android/syncadapter/FileSyncAdapter.java
index 46c088b45d..4eafeac56d 100644
--- a/src/com/owncloud/android/syncadapter/FileSyncAdapter.java
+++ b/src/com/owncloud/android/syncadapter/FileSyncAdapter.java
@@ -19,7 +19,6 @@
package com.owncloud.android.syncadapter;
import java.io.IOException;
-import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -35,11 +34,11 @@ import com.owncloud.android.operations.RemoteOperationResult;
import com.owncloud.android.operations.SynchronizeFolderOperation;
import com.owncloud.android.operations.UpdateOCVersionOperation;
import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.ui.activity.AuthenticatorActivity;
import com.owncloud.android.ui.activity.ErrorsWhileCopyingHandlerActivity;
+
import android.accounts.Account;
import android.accounts.AccountsException;
-import android.accounts.AuthenticatorException;
-import android.accounts.OperationCanceledException;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -249,6 +248,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
RemoteOperationResult.ResultCode code = failedResult.getCode();
return (code.equals(RemoteOperationResult.ResultCode.SSL_ERROR) ||
code.equals(RemoteOperationResult.ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED) ||
+ code.equals(RemoteOperationResult.ResultCode.UNAUTHORIZED) ||
code.equals(RemoteOperationResult.ResultCode.BAD_OC_VERSION) ||
code.equals(RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED));
}
@@ -299,12 +299,29 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
private void notifyFailedSynchronization() {
Notification notification = new Notification(R.drawable.icon, getContext().getString(R.string.sync_fail_ticker), System.currentTimeMillis());
notification.flags |= Notification.FLAG_AUTO_CANCEL;
- // TODO put something smart in the contentIntent below
+ boolean needsToUpdateCredentials = (mLastFailedResult != null && mLastFailedResult.getCode() == ResultCode.UNAUTHORIZED);
+ // TODO put something smart in the contentIntent below for all the possible errors
notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0);
- notification.setLatestEventInfo(getContext().getApplicationContext(),
- getContext().getString(R.string.sync_fail_ticker),
- String.format(getContext().getString(R.string.sync_fail_content), getAccount().name),
- notification.contentIntent);
+ if (needsToUpdateCredentials) {
+ // let the user update credentials with one click
+ Intent updateAccountCredentials = new Intent(getContext(), AuthenticatorActivity.class);
+ updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACCOUNT, getAccount());
+ updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACTION, AuthenticatorActivity.ACTION_UPDATE_TOKEN);
+ updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ updateAccountCredentials.addFlags(Intent.FLAG_FROM_BACKGROUND);
+ notification.contentIntent = PendingIntent.getActivity(getContext(), (int)System.currentTimeMillis(), updateAccountCredentials, PendingIntent.FLAG_ONE_SHOT);
+ notification.setLatestEventInfo(getContext().getApplicationContext(),
+ getContext().getString(R.string.sync_fail_ticker),
+ String.format(getContext().getString(R.string.sync_fail_content_unauthorized), getAccount().name),
+ notification.contentIntent);
+ Log.e(TAG, "NEEDS TO UPDATE CREDENTIALS");
+ } else {
+ notification.setLatestEventInfo(getContext().getApplicationContext(),
+ getContext().getString(R.string.sync_fail_ticker),
+ String.format(getContext().getString(R.string.sync_fail_content), getAccount().name),
+ notification.contentIntent);
+ }
((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(R.string.sync_fail_ticker, notification);
}
diff --git a/src/com/owncloud/android/ui/activity/AuthenticatorActivity.java b/src/com/owncloud/android/ui/activity/AuthenticatorActivity.java
index 8c8798c596..8dce3bc2f5 100644
--- a/src/com/owncloud/android/ui/activity/AuthenticatorActivity.java
+++ b/src/com/owncloud/android/ui/activity/AuthenticatorActivity.java
@@ -186,8 +186,6 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
/// retrieve extras from intent
String tokenType = getIntent().getExtras().getString(AccountAuthenticator.KEY_AUTH_TOKEN_TYPE);
boolean oAuthRequired = AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN.equals(tokenType);
- mOAuth2Check.setChecked(oAuthRequired);
- changeViewByOAuth2Check(oAuthRequired);
mAccount = getIntent().getExtras().getParcelable(EXTRA_ACCOUNT);
if (mAccount != null) {
@@ -199,7 +197,11 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
mHostUrlInput.setText(mHostBaseUrl);
String userName = mAccount.name.substring(0, mAccount.name.lastIndexOf('@'));
mUsernameInput.setText(userName);
+ oAuthRequired = (mAccountMgr.getUserData(mAccount, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null);
}
+ mOAuth2Check.setChecked(oAuthRequired);
+ changeViewByOAuth2Check(oAuthRequired);
+
} else {
loadSavedInstanceState(savedInstanceState);
@@ -826,11 +828,10 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
boolean isOAuth = mOAuth2Check.isChecked();
if (isOAuth) {
response.putString(AccountManager.KEY_AUTHTOKEN, mOAuthAccessToken);
- // the next line is unnecessary; the AccountManager does it when receives the response Bundle
- // mAccountMgr.setAuthToken(mAccount, AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN, mOAuthAccessToken);
+ // the next line is necessary; by now, notifications are calling directly to the AuthenticatorActivity to update, without AccountManager intervention
+ mAccountMgr.setAuthToken(mAccount, AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN, mOAuthAccessToken);
} else {
response.putString(AccountManager.KEY_AUTHTOKEN, mPasswordInput.getText().toString());
- // the next line is not really necessary, because we are using the password as if it was an auth token; but let's keep it there by now
mAccountMgr.setPassword(mAccount, mPasswordInput.getText().toString());
}
setAccountAuthenticatorResult(response);