android - 安卓账户
问题描述
在实现 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();
}
}
}
我有两个问题:
MainActivity 中有一条注释:“如果登录的帐户不存在,我们需要在设备上创建它”。如果我们刚刚获得身份验证令牌的帐户不存在并且我们需要通过我们刚刚从中获得的数据添加它,这种情况怎么会发生?
在这个问题中,用户名(此处的电子邮件)已保存为 account_name。我想这只是为了测试实施,但一般来说,如果我想保存一些关于我想保存在帐户中的用户的数据,比如用户名等,我该怎么做?可以说与添加这样的帐户密码相反:
mAccountManager.addAccountExplicitly(account, accountPassword, null);
解决方案
推荐阅读
- amazon-web-services - 在本地计算机上使用来自 Amazon Sagemaker 的标记数据,而无需进一步依赖 AWS
- apache-spark - Pyspark 中的 K-NN
- python-3.x - 使用 pandas 的多列中最常出现的数字
- ruby-on-rails - React 兼容的 JS OAuth 客户端 - Rails Doorkeeper
- asp.net - 阻止 Chrome 发送无缓存无存储标头
- node.js - ffmpeg nodejs lambda裁剪问题
- laravel - Laravel 7 API 电子邮件验证未更新 email_verified_at
- python - Pycharm pygmsh error AssertionError: Gmsh exited with error (return code 3221225781)
- php - WooCommerce:检查购物车中不同购物车商品/ SKU 的数量
- machine-learning - 机器学习模型的部署 - 数据版本控制