Can't get my account to show in Android's accounts... can anyone have a look?
Lot of code... I got this from Android's official sample code, SampleSyncAdapter
Anyways here is the code. I did not include the syncing classes, I just want to get the account to show up and be able to be created for now.
Account Authenticator class:
package com.tagapp.android;
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;
public class AccountAuthenticator extends AbstractAccountAuthenticator {
private Context mContext;
public AccountAuthenticator(Context context) {
super(context);
mContext = context;
}
@Override
public Bundle addAccount(AccountAuthenticatorResponse response,
String accountType, String authTokenType,
String[] requiredFeatures, Bundle options) {
Intent intent = new Intent(mContext, AuthenticatorActivity.class);
intent.putExtra(AuthenticatorActivity.PARAM_AUTHTOKEN_TYPE, authTokenType);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
return bundle;
}
@Override
public Bundle confirmCredentials(AccountAuthenticatorResponse response,
Account account, Bundle options) throws NetworkErrorException {
if(options != null && options.containsKey(AccountManager.KEY_PASSWORD)) {
String password = options.getString(AccountManager.KEY_PASSWORD);
boolean verified = onlineConfirmPassword(account.name, password);
Bundle result = new Bundle();
result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, verified);
return result;
}
Intent intent = new Intent(mContext, AuthenticatorActivity.class);
intent.putExtra(AuthenticatorActivity.PARAM_USERNAME, account.name);
intent.putExtra(AuthenticatorActivity.PARAM_CONFIRM_CREDENTIALS, true);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
return bundle;
}
private boolean onlineConfirmPassword(String username, String password) {
return RestClient.authenticate(username, password, null, null);
}
@Override
public Bundle editProperties(AccountAuthenticatorResponse response,
String accountType) {
throw new UnsupportedOperationException();
}
@Override
public Bundle getAuthToken(AccountAuthenticatorResponse response,
Account account, String authTokenType, Bundle options) {
if(!authTokenType.equals("com.tagapp.android")) {
Bundle result = new Bundle();
result.putString(AccountManager.KEY_ERROR_MESSAGE, "invalid authtokenType");
return result;
}
AccountManager am = AccountManager.get(mContext);
String password = am.getPassword(account);
if(password != null) {
boolean verified = onlineConfirmPassword(account.name, password);
if(verified) {
Bundle result = new Bundle();
result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, "com.tagapp.android");
result.putString(AccountManager.KEY_AUTHTOKEN, password);
return result;
}
}
Intent intent = new Intent(mContext, AuthenticatorActivity.class);
intent.putExtra(AuthenticatorActivity.PARAM_USERNAME, account.name);
intent.putExtra(AuthenticatorActivity.PARAM_AUTHTOKEN_TYPE, authTokenType);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
return bundle;
}
@Override
public String getAuthTokenLabel(String authTokenType) {
if("com.tagapp.android".equals(authTokenType)) {
return "Tag";
}
return null;
}
@Override
public Bundle hasFeatures(AccountAuthenticatorResponse response,
Account account, String[] features) throws NetworkErrorException {
Bundle result = new Bundle();
result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false);
return result;
}
@Override
public Bundle updateCredentials(AccountAuthenticatorResponse response,
Account account, String authTokenType, Bundle options) {
Intent intent = new Intent(mContext, AuthenticatorActivity.class);
intent.putExtra(AuthenticatorActivity.PARAM_USERNAME, account.name);
intent.putExtra(AuthenticatorActivity.PARAM_AUTHTOKEN_TYPE, authTokenType);
intent.putExtra(AuthenticatorActivity.PARAM_CONFIRM_CREDENTIALS, false);
Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
return bundle;
}
}
AccountAuthenticationActivity class:
package com.tagapp.android;
import android.accounts.Account;
import android.accounts.AccountAuthenticatorActivity;
import android.accounts.AccountManager;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.ContentResolver;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.provider.ContactsContract;
import android.text.TextUtils;
import android.view.View;
import android.view.Window;
import android.widget.EditText;
import android.widget.TextView;
public class AuthenticatorActivity extends AccountAuthenticatorActivity {
public static final String PARAM_AUTHTOKEN_TYPE = "authtokenType";
public static final String PARAM_USERNAME = "username";
public static final String PARAM_CONFIRM_CREDENTIALS = "confirmCredentials";
public static final String PARAM_PASSWORD = "password";
private AccountManager mAccountManager;
private Thread mAuthThread;
private String mAuthtoken;
private String mAuthtokenType;
private Boolean mConfirmCredentials = false;
private final Handler mHandler = new Handler();
private TextView mMessageView;
private String mPassword;
private String mUsername;
private EditText mPasswordEdit;
private EditText mUsernameEdit;
private boolean mRequestNewAccount = false;
@Overr开发者_StackOverflowide
public void onCreate(Bundle neato) {
super.onCreate(neato);
mAccountManager = AccountManager.get(this);
Intent intent = getIntent();
mUsername = intent.getStringExtra(PARAM_USERNAME);
mAuthtokenType = intent.getStringExtra(PARAM_AUTHTOKEN_TYPE);
mConfirmCredentials = intent.getBooleanExtra(PARAM_CONFIRM_CREDENTIALS, false);
initLayout();
}
private void initLayout() {
setContentView(R.layout.account_sync_login);
requestWindowFeature(Window.FEATURE_LEFT_ICON);
mMessageView = (TextView)findViewById(R.id.account_login_message);
mUsernameEdit = (EditText)findViewById(R.id.account_login_username_edittext);
mPasswordEdit = (EditText)findViewById(R.id.account_login_password_edittext);
mUsernameEdit.setText(mUsername);
if(getMessage() != null) {
mMessageView.setText(getMessage());
}
}
private CharSequence getMessage() {
if(TextUtils.isEmpty(mUsername)) {
CharSequence msg = "Enter your username and password.";
return msg;
}
if(TextUtils.isEmpty(mPassword)) {
return "Enter your password.";
}
return null;
}
@Override
protected Dialog onCreateDialog(int id) {
ProgressDialog dialog = new ProgressDialog(this);
dialog.setMessage("Authenticating...");
dialog.setIndeterminate(true);
dialog.setCancelable(true);
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
if(mAuthThread != null) {
mAuthThread.interrupt();
finish();
}
}
});
return dialog;
}
public void handleLogin(View v) {
if(mRequestNewAccount) {
mUsername = mUsernameEdit.getText().toString();
}
mPassword = mPasswordEdit.getText().toString();
if(TextUtils.isEmpty(mUsername) || TextUtils.isEmpty(mPassword)) {
mMessageView.setText(getMessage());
}
else {
showProgress();
mAuthThread = RestClient.attemptAuth(mUsername, mPassword, mHandler, this);
}
}
private void finishConfirmCredentials(boolean result) {
Account account = new Account(mUsername, "com.tagapp.android");
mAccountManager.setPassword(account, mPassword);
Intent intent = new Intent();
intent.putExtra(AccountManager.KEY_BOOLEAN_RESULT, result);
setAccountAuthenticatorResult(intent.getExtras());
setResult(RESULT_OK, intent);
finish();
}
private void finishLogin() {
Account account = new Account(mUsername, "com.taggapp.android");
if(mRequestNewAccount) {
mAccountManager.addAccountExplicitly(account, mPassword, null);
ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true);
}
else {
mAccountManager.setPassword(account, mPassword);
}
Intent intent = new Intent();
mAuthtoken = mPassword;
intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, mUsername);
intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, "com.tagapp.android");
if(mAuthtokenType != null && mAuthtokenType.equals("com.tagapp.android")) {
intent.putExtra(AccountManager.KEY_AUTHTOKEN, mAuthtoken);
}
setAccountAuthenticatorResult(intent.getExtras());
setResult(RESULT_OK, intent);
finish();
}
private void showProgress() {
showDialog(0);
}
private void hideProgress() {
dismissDialog(0);
}
public void onAuthenticationResult(boolean result) {
hideProgress();
if(result) {
if(!mConfirmCredentials) {
finishLogin();
}
else {
finishConfirmCredentials(true);
}
}
else {
if(mRequestNewAccount) {
mMessageView.setText("You got it all wrong.");
}
else {
mMessageView.setText("Wrong password.");
}
}
}
}
AuthenticatorService class:
package com.tagapp.android;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class AccountAuthenticatorService extends Service {
private AccountAuthenticator mAuthenticator;
@Override
public void onCreate() {
mAuthenticator = new AccountAuthenticator(this);
}
@Override
public IBinder onBind(Intent intent) {
return mAuthenticator.getIBinder();
}
}
Manifest includes the following:
<service android:name=".authenticator.AccountAuthenticatorService"
android:exported="true">
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator" />
</intent-filter>
<meta-data android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/authenticator"/>
</service>
and...
<activity android:name=".AuthenticatorActivity"
android:label="Sync Tag Account!"
android:theme="@android:style/Theme.Dialog"
android:excludeFromRecents="true">
The xml file referenced in the service is here:
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="com.tagapp.android"
android:icon="@drawable/taglogo"
android:smallIcon="@drawable/launchicon"
android:label="Tag"/>
I know this is a lot of code... but I've become pretty desperate trying to find a result for this. From what I understand this should work just fine, but when I go to add an account it times out/crashes, or just doesn't show my app's account as an option to add. I've tried this both in the emulator and my actual Android phone, neither work. No errors are produced in Logcat when it fails. If anyone has experience with this and could provide some sample code/insight as to why my code isn't working, I'd really appreciate it... thanks a lot!
I don't see your columns interface file. It defines your custom MIME_PROFILE and which columns in the Data table your contact data is stored in.
精彩评论