首页 > 解决方案 > 安卓账户

问题描述

在实现 android 帐户身份验证期间,我遇到了这个示例(如果有人想学习该过程,这将非常有帮助)。

这是一些相关的代码,最后我有两个问题。

public class MainActivity extends Activity {

        private static final int REQ_SIGNUP = 1;

        private AccountManager mAccountManager;
        private AuthPreferences mAuthPreferences;
        private String authToken;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            authToken = null;
            mAuthPreferences = new AuthPreferences(this);
            mAccountManager = AccountManager.get(this);

            // Ask for an auth token
            mAccountManager.getAuthTokenByFeatures(AccountUtils.ACCOUNT_TYPE, AccountUtils.AUTH_TOKEN_TYPE, null, this, null, null, new GetAuthTokenCallback(), null);
        }

        private class GetAuthTokenCallback implements AccountManagerCallback<Bundle> {

            @Override
            public void run(AccountManagerFuture<Bundle> result) {
                Bundle bundle;

                try {
                    bundle = result.getResult();

                    final Intent intent = (Intent) bundle.get(AccountManager.KEY_INTENT);
                    if (null != intent) {
                        startActivityForResult(intent, REQ_SIGNUP);
                    } else {
                        authToken = bundle.getString(AccountManager.KEY_AUTHTOKEN);
                        final String accountName = bundle.getString(AccountManager.KEY_ACCOUNT_NAME);

                        // Save session username & auth token
                        mAuthPreferences.setAuthToken(authToken);
                        mAuthPreferences.setUsername(accountName);


                        // If the logged account didn't exist, we need to create it on the device
                        Account account = AccountUtils.getAccount(MainActivity.this, accountName);
                        if (null == account) {
                            account = new Account(accountName, AccountUtils.ACCOUNT_TYPE);
                            mAccountManager.addAccountExplicitly(account, bundle.getString(LoginActivity.PARAM_USER_PASSWORD), null);
                            mAccountManager.setAuthToken(account, AccountUtils.AUTH_TOKEN_TYPE, authToken);
                        }
                    }
                } catch(OperationCanceledException e) {
                    // If signup was cancelled, force activity termination
                    finish();
                } catch(Exception e) {
                    e.printStackTrace();
                }

            }

        }
    .
    .
    .
}

这是 AccountAuthenticator 的代码:

public class AccountAuthenticator extends AbstractAccountAuthenticator {

    private final Context mContext;

    public AccountAuthenticator(Context context) {  
        super(context);
        mContext = context;
    }  

    @Override
    public Bundle addAccount(
        AccountAuthenticatorResponse response, 
        String accountType,
        String authTokenType, 
        String[] requiredFeatures, 
        Bundle options)
    throws NetworkErrorException
    {
        Bundle reply = new Bundle();

        Intent intent = new Intent(mContext, LoginActivity.class);
        intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
        intent.putExtra(LoginActivity.ARG_ACCOUNT_TYPE, accountType);
        intent.putExtra(LoginActivity.ARG_AUTH_TOKEN_TYPE, authTokenType);
        intent.putExtra(LoginActivity.ARG_IS_ADDING_NEW_ACCOUNT, true);

        // return our AccountAuthenticatorActivity
        reply.putParcelable(AccountManager.KEY_INTENT, intent);

        return reply;
    }

    @Override
    public Bundle confirmCredentials(AccountAuthenticatorResponse arg0,
            Account arg1, Bundle arg2) throws NetworkErrorException {
        return null;
    }

    @Override
    public Bundle editProperties(AccountAuthenticatorResponse arg0, String arg1) {
        return null;
    }

    @Override
    public Bundle getAuthToken(
        AccountAuthenticatorResponse response, 
        Account account,
        String authTokenType, 
        Bundle options) 
    throws NetworkErrorException 
    {
        // Extract the username and password from the Account Manager, and ask
        // the server for an appropriate AuthToken.
        final AccountManager am = AccountManager.get(mContext);

        String authToken = am.peekAuthToken(account, authTokenType);

        // Lets give another try to authenticate the user
        if (null != authToken) {
            if (authToken.isEmpty()) {
                final String password = am.getPassword(account);
                if (password != null) {
                    authToken = AccountUtils.mServerAuthenticator.signIn(account.name, password);
                }
            }
        }

        // If we get an authToken - we return it
        if (null != authToken) {
            if (!authToken.isEmpty()) {
                final Bundle result = new Bundle();
                result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
                result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
                result.putString(AccountManager.KEY_AUTHTOKEN, authToken);
                return result;
            }
        }

        // If we get here, then we couldn't access the user's password - so we
        // need to re-prompt them for their credentials. We do that by creating
        // an intent to display our AuthenticatorActivity.
        final Intent intent = new Intent(mContext, LoginActivity.class);
        intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
        intent.putExtra(LoginActivity.ARG_ACCOUNT_TYPE, account.type);
        intent.putExtra(LoginActivity.ARG_AUTH_TOKEN_TYPE, authTokenType);

        // This is for the case multiple accounts are stored on the device
        // and the AccountPicker dialog chooses an account without auth token.
        // We can pass out the account name chosen to the user of write it
        // again in the Login activity intent returned.
        if (null != account) {
            intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, account.name);
        }

        final Bundle bundle = new Bundle();
        bundle.putParcelable(AccountManager.KEY_INTENT, intent);

        return bundle;
    }

    @Override
    public String getAuthTokenLabel(String arg0) {
        return null;
    }

    @Override
    public Bundle hasFeatures(AccountAuthenticatorResponse arg0, Account arg1,
            String[] arg2) throws NetworkErrorException {
        return null;
    }

    @Override
    public Bundle updateCredentials(AccountAuthenticatorResponse arg0,
            Account arg1, String arg2, Bundle arg3)
            throws NetworkErrorException {
        return null;
    }

}

这是 AccountAuthenticatorActivity:

public class LoginActivity extends AccountAuthenticatorActivity {

    public static final String ARG_ACCOUNT_TYPE = "accountType";
    public static final String ARG_AUTH_TOKEN_TYPE = "authTokenType";
    public static final String ARG_IS_ADDING_NEW_ACCOUNT = "isAddingNewAccount";
    public static final String PARAM_USER_PASSWORD = "password";

    private AccountManager mAccountManager;

.
.
.
        Intent res = new Intent
        res.putExtra(AccountManager.KEY_ACCOUNT_NAME, mEmail);
        res.putExtra(AccountManager.KEY_ACCOUNT_TYPE, AccountUtils.ACCOUNT_TYPE);
        res.putExtra(AccountManager.KEY_AUTHTOKEN, authToken);
        res.putExtra(PARAM_USER_PASSWORD, mPassword);

        finishLogin(res);

.
.
.


        private void finishLogin(Intent intent) {
            final String accountName = intent.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
            final String accountPassword = intent.getStringExtra(PARAM_USER_PASSWORD);
            final Account account = new Account(accountName, intent.getStringExtra(AccountManager.KEY_ACCOUNT_TYPE));
            String authToken = intent.getStringExtra(AccountManager.KEY_AUTHTOKEN);

            if (getIntent().getBooleanExtra(ARG_IS_ADDING_NEW_ACCOUNT, false)) {
                // Creating the account on the device and setting the auth token we got
                // (Not setting the auth token will cause another call to the server to authenticate the user)
                mAccountManager.addAccountExplicitly(account, accountPassword, null);
                mAccountManager.setAuthToken(account, AccountUtils.AUTH_TOKEN_TYPE, authToken);
            } else {
                mAccountManager.setPassword(account, accountPassword);
            }

            setAccountAuthenticatorResult(intent.getExtras());
            setResult(AccountAuthenticatorActivity.RESULT_OK, intent);

            finish();
        }
    }
}

我有两个问题:

  1. MainActivity 中有一条注释:“如果登录的帐户不存在,我们需要在设备上创建它”。如果我们刚刚获得身份验证令牌的帐户不存在并且我们需要通过我们刚刚从中获得的数据添加它,这种情况怎么会发生?

  2. 在这个问题中,用户名(此处的电子邮件)已保存为 account_name。我想这只是为了测试实施,但一般来说,如果我想保存一些关于我想保存在帐户中的用户的数据,比如用户名等,我该怎么做?可以说与添加这样的帐户密码相反:

mAccountManager.addAccountExplicitly(account, accountPassword, null);

标签: androidandroid-account

解决方案


推荐阅读