/**
*
*/
package fm.last.android.sync;
import fm.last.android.LastFMApplication;
import fm.last.android.LastFm;
import fm.last.android.R;
import fm.last.android.activity.AccountAccessPrompt;
import fm.last.android.activity.AccountFailActivity;
import fm.last.api.MD5;
import android.accounts.AbstractAccountAuthenticator;
import android.accounts.Account;
import android.accounts.AccountAuthenticatorResponse;
import android.accounts.AccountManager;
import android.accounts.NetworkErrorException;
import android.app.Service;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcelable;
import android.preference.PreferenceManager;
import android.provider.ContactsContract;
import android.util.Log;
/**
* @author sam
*
*/
public class AccountAuthenticatorService extends Service {
private static final String TAG = "AccountAuthenticatorService";
private static AccountAuthenticatorImpl sAccountAuthenticator = null;
public AccountAuthenticatorService() {
super();
}
private static class AccountAuthenticatorImpl extends AbstractAccountAuthenticator {
private Context mContext;
public AccountAuthenticatorImpl(Context context) {
super(context);
mContext = context;
}
public static Bundle addAccount(Context ctx, String username, String password) {
Bundle result = null;
Account account = new Account(username, ctx.getString(R.string.ACCOUNT_TYPE));
AccountManager am = AccountManager.get(ctx);
if (am.addAccountExplicitly(account, MD5.getInstance().hash(password), null)) {
result = new Bundle();
result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
}
return result;
}
public static Boolean hasLastfmAccount(Context ctx) {
AccountManager am = AccountManager.get(ctx);
Account[] accounts = am.getAccountsByType(ctx.getString(R.string.ACCOUNT_TYPE));
if(accounts != null && accounts.length > 0)
return true;
else
return false;
}
public static void removeLastfmAccount(Context ctx) {
AccountManager am = AccountManager.get(ctx);
Account[] accounts = am.getAccountsByType(ctx.getString(R.string.ACCOUNT_TYPE));
for(Account account : accounts) {
am.removeAccount(account, null, null);
}
}
/* (non-Javadoc)
* @see android.accounts.AbstractAccountAuthenticator#addAccount(android.accounts.AccountAuthenticatorResponse, java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle)
*/
@Override
public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options)
throws NetworkErrorException {
Bundle result;
if(hasLastfmAccount(mContext)) {
result = new Bundle();
Intent i = new Intent(mContext, AccountFailActivity.class);
i.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
result.putParcelable(AccountManager.KEY_INTENT, i);
return result;
} else {
result = new Bundle();
Intent i = new Intent(mContext, LastFm.class);
i.setAction("fm.last.android.sync.LOGIN");
i.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
result.putParcelable(AccountManager.KEY_INTENT, i);
}
return result;
}
/* (non-Javadoc)
* @see android.accounts.AbstractAccountAuthenticator#confirmCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, android.os.Bundle)
*/
@Override
public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) {
// TODO Auto-generated method stub
Log.i(TAG, "confirmCredentials");
return null;
}
/* (non-Javadoc)
* @see android.accounts.AbstractAccountAuthenticator#editProperties(android.accounts.AccountAuthenticatorResponse, java.lang.String)
*/
@Override
public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
// TODO Auto-generated method stub
Log.i(TAG, "editProperties");
return null;
}
/* (non-Javadoc)
* @see android.accounts.AbstractAccountAuthenticator#getAuthToken(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String, android.os.Bundle)
*/
@Override
public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
String api_key = options.getString("api_key");
String api_secret = options.getString("api_secret");
AccountManager am = AccountManager.get(mContext);
String user = account.name.toLowerCase().trim();
String md5Password = am.getPassword(account);
String authToken = MD5.getInstance().hash(user + md5Password);
Bundle result = new Bundle();
Intent i = new Intent(mContext, AccountAccessPrompt.class);
i.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
i.putExtra("api_key", api_key);
i.putExtra("api_secret", api_secret);
i.putExtra("user", user);
i.putExtra("authToken", authToken);
result.putParcelable(AccountManager.KEY_INTENT, i);
return result;
}
/* (non-Javadoc)
* @see android.accounts.AbstractAccountAuthenticator#getAuthTokenLabel(java.lang.String)
*/
@Override
public String getAuthTokenLabel(String authTokenType) {
// TODO Auto-generated method stub
Log.i(TAG, "getAuthTokenLabel");
return null;
}
/* (non-Javadoc)
* @see android.accounts.AbstractAccountAuthenticator#hasFeatures(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String[])
*/
@Override
public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) throws NetworkErrorException {
// TODO Auto-generated method stub
Log.i(TAG, "hasFeatures: " + features);
return null;
}
/* (non-Javadoc)
* @see android.accounts.AbstractAccountAuthenticator#updateCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String, android.os.Bundle)
*/
@Override
public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) {
// TODO Auto-generated method stub
Log.i(TAG, "updateCredentials");
return null;
}
}
@Override
public IBinder onBind(Intent intent) {
IBinder ret = null;
if (intent.getAction().equals(android.accounts.AccountManager.ACTION_AUTHENTICATOR_INTENT))
ret = getAuthenticator().getIBinder();
return ret;
}
public static void addAccount(Context ctx, String username, String password, Parcelable response) {
AccountAuthenticatorResponse authResponse = (AccountAuthenticatorResponse)response;
Bundle result = AccountAuthenticatorImpl.addAccount(ctx, username, password);
if(authResponse != null)
authResponse.onResult(result);
}
public static Boolean hasLastfmAccount(Context ctx) {
return AccountAuthenticatorImpl.hasLastfmAccount(ctx);
}
public static void removeLastfmAccount(Context ctx) {
AccountAuthenticatorImpl.removeLastfmAccount(ctx);
}
public static void resyncAccount(Context context) {
Editor editor = PreferenceManager.getDefaultSharedPreferences(LastFMApplication.getInstance()).edit();
editor.putBoolean("do_full_sync", true);
editor.commit();
AccountManager am = AccountManager.get(context);
Account[] accounts = am.getAccountsByType(context.getString(R.string.ACCOUNT_TYPE));
if(ContentResolver.getSyncAutomatically(accounts[0], ContactsContract.AUTHORITY)) {
//Try turning it off and on again
ContentResolver.setSyncAutomatically(accounts[0], ContactsContract.AUTHORITY, false);
ContentResolver.setSyncAutomatically(accounts[0], ContactsContract.AUTHORITY, true);
}
}
private AccountAuthenticatorImpl getAuthenticator() {
if (sAccountAuthenticator == null)
sAccountAuthenticator = new AccountAuthenticatorImpl(this);
return sAccountAuthenticator;
}
}