I'm new to Android / Xamarin but have been unable to overcome a hurdle while trying to implement a custom AccountAuthenticator. There is startingly little available in forums & documentation. I've been able to get the new Account type to show up when selecting Accounts & Sync > New Account, but as soon as I hit New Account, it simply goes back to the Accounts & Sync screen. I have the following code: AccountAuthenticatorService.cs (which contains both of the necessary classes, implementing the Service and the AccountAuthenticator) Note that it appears that the Custom Attributes below can be used in leiu of the normal clauses for implementing this in the AndroidManifest.
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Accounts;
/*This file contains both the AccountAuthenticator as well as the AccountAuthenticatorService */
namespace MyApp.Src.Services {
[Service]
[IntentFilter(new[] { "android.accounts.AccountAuthenticator" })]
[MetaData("android.accounts.AccountAuthenticator", Resource="@xml/authenticator")]
class AccountAuthenticatorService : Service {
private static AccountAuthenticator sAccountAuthenticator = null;
public static string ACCOUNT_TYPE = "com.myapp.account";
public static string ACCOUNT_NAME = "MyApp";
private Context _context;
public AccountAuthenticatorService() : base() {
Console.WriteLine("Default Contructor");
}
public AccountAuthenticatorService(Context _context) : base() {
Console.WriteLine("Secondary Constructor");
this._context = _context;
}
public override IBinder OnBind(Intent intent) {
Console.WriteLine("OnBind");
IBinder ret = null;
if (intent.Action == Android.Accounts.AccountManager.ActionAuthenticatorIntent)
ret = getAuthenticator().IBinder;
return ret;
}
private AccountAuthenticator getAuthenticator() {
Console.WriteLine("getAuthenticator");
if (sAccountAuthenticator == null)
sAccountAuthenticator = new AccountAuthenticator(this._context);
return sAccountAuthenticator;
}
}
/* Enclosing the Account Authenticator in here as well */
public class AccountAuthenticator : Android.Accounts.AbstractAccountAuthenticator {
private Context mContext;
public AccountAuthenticator(Context context)
: base(context) {
Console.WriteLine("AccountAuthenticator");
mContext = context;
}
public override Bundle AddAccount(Android.Accounts.AccountAuthenticatorResponse response, string accountType, string authTokenType, string[] requiredFeatures, Bundle options) {
try {
Console.WriteLine("Add Account");
Intent intent = new Intent(this.mContext, typeof(iCRMAndroid.Src.Activities.LoginActivity));
intent.PutExtra(AccountManager.KeyAccountAuthenticatorResponse, response);
Bundle result = new Bundle();
result.PutParcelable(AccountManager.KeyIntent, intent);
return result;
} catch (System.Exception ex) {
throw ex;
}
}
//Stub Method
public override Bundle ConfirmCredentials(Android.Accounts.AccountAuthenticatorResponse response, Android.Accounts.Account account, Android.OS.Bundle options) {
Console.WriteLine("Confirm Credentials");
return this.ConfirmCredentials(response, account, options);
}
//Stub Method
public override Bundle GetAuthToken(AccountAuthenticatorResponse r, Account account, String s, Bundle bundle) {
Console.WriteLine("Get Auth Token");
throw new Java.Lang.UnsupportedOperationException();
}
//Stub Method
public override String GetAuthTokenLabel(String s) {
Console.WriteLine("Get Auth Token Label");
throw new Java.Lang.UnsupportedOperationException();
}
//Stub Method
public override Bundle UpdateCredentials(AccountAuthenticatorResponse r, Account account, String s, Bundle bundle) {
Console.WriteLine("Update Credentials");
throw new Java.Lang.UnsupportedOperationException();
}
//Stub Method
public override Bundle HasFeatures(AccountAuthenticatorResponse r, Account account, String[] strings) {
Console.WriteLine("Has Featurea");
throw new Java.Lang.UnsupportedOperationException();
}
//Stub Method
public override Bundle EditProperties(AccountAuthenticatorResponse r, String s) {
Console.WriteLine("Edit Properties");
throw new Java.Lang.UnsupportedOperationException();
}
}
}
authenticator.xml <?xml version="1.0" encoding="utf-8" ?>
When I debug the app and follow the Android Device Log, I see two things that are interesting: 1. The following methods are hit, based on the debug statements above: "Default Constructor", "getAuthenticator", "Account Authenticator" and that's it. I don't see an error, it just fails to trigger the Login Activity - and goes back to the Accounts & Sync screen. 2. An error I do sometimes see indicates a StrictMode violation, and I can't tell if this is meaningful or a red herring. "class com.android.settings.accounts.AddAccountSettings; instances=2; limit=1" with a later error including "StrictMode$InstanceCountViolation."
Any thoughts would be appreciated! Thanks!