/*
* Copyright (c) 2014-2015 Sean Liu.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.baoti.authprovider.accounts;
import android.accounts.AbstractAccountAuthenticator;
import android.accounts.Account;
import android.accounts.AccountAuthenticatorResponse;
import android.accounts.AccountManager;
import android.accounts.NetworkErrorException;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import timber.log.Timber;
import static android.accounts.AccountManager.KEY_ACCOUNT_NAME;
import static android.accounts.AccountManager.KEY_ACCOUNT_TYPE;
import static android.accounts.AccountManager.KEY_AUTHTOKEN;
import static android.accounts.AccountManager.KEY_INTENT;
/**
* Created by liuyedong on 15-1-19.
*/
class AccountAuthenticator extends AbstractAccountAuthenticator implements AccountConstants {
private final Context context;
public AccountAuthenticator(Context context) {
super(context);
this.context = context;
}
@Override
public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
// 用于显示设置界面
return null;
}
@Override
public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) throws NetworkErrorException {
Timber.d("[addAccount] - accountType: %s, authTokenType: %s", accountType, authTokenType);
Bundle result = new Bundle();
result.putParcelable(KEY_INTENT, createActivityIntent(response, authTokenType));
return result;
}
@Override
public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) throws NetworkErrorException {
// 用于明确提醒用户进行登录, options中可携带KEY_PASSWORD, 用于直接登录
return null;
}
@Override
public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
Timber.d("[getAuthToken] - account: %s, authTokenType: %s", account, authTokenType);
Bundle result = new Bundle();
if (!authTokenType.equals(AUTH_TOKEN_TYPE_PIONEER)) {
return result;
}
AccountManager am = AccountManager.get(context);
String password = am.getPassword(account);
if (TextUtils.isEmpty(password)) {
result.putParcelable(KEY_INTENT, createActivityIntent(response, authTokenType));
return result;
}
String authToken = getOrCreateAuthorization(account.name, password);
if (TextUtils.isEmpty(authToken)) {
result.putParcelable(KEY_INTENT, createActivityIntent(response, authTokenType));
} else {
result.putString(KEY_ACCOUNT_NAME, account.name);
result.putString(KEY_ACCOUNT_TYPE, ACCOUNT_TYPE);
result.putString(KEY_AUTHTOKEN, authToken);
am.clearPassword(account);
}
return result;
}
private String getOrCreateAuthorization(String user, String password) {
return user.substring(0, 2) + ":" + password.substring(0, Math.min(1, password.length()));
}
private Intent createActivityIntent(AccountAuthenticatorResponse response, String authTokenType) {
return AuthenticatorActivity.actionAuthenticate(context, response, authTokenType);
}
@Override
public String getAuthTokenLabel(String authTokenType) {
if (AUTH_TOKEN_TYPE_PIONEER.equals(authTokenType)) {
return "Pioneer";
}
return null;
}
@Override
public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
// authToken 失效 或 密码变更时, 此方法可重新请求 authToken 或 要求用户登录
return null;
}
@Override
public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) throws NetworkErrorException {
Bundle result = new Bundle();
boolean pass = true;
if (features != null) {
for (String feature : features) {
if (!FEATURE_READ_NEWS.equals(feature)) {
pass = false;
break;
}
}
}
result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, pass);
return result;
}
}