/* * 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; } }