package com.iwedia.service.system.account;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorDescription;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SyncAdapterType;
import android.content.SyncStatusObserver;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Log;
import com.iwedia.comm.system.account.Account;
import com.iwedia.service.IWEDIAService;
import com.iwedia.service.system.SystemControl;
public class AccountAndSyncManager {
/**
* Extra parameter to identify the caller. Applications may display a
* different UI if the calls is made from Settings or from a specific
* application.
*/
private static final String KEY_CALLER_IDENTITY = "pendingIntent";
private static final String TAG = "AccountAndSyncManager";
/* package */static final String EXTRA_SELECTED_ACCOUNT = "selected_account";
// show additional info regarding the use of a device with multiple users
static final String EXTRA_HAS_MULTIPLE_USERS = "hasMultipleUsers";
private static AccountAndSyncManager instance;
private PendingIntent mPendingIntent;
public HashSet<String> mAccountTypesFilter;
@SuppressWarnings("unused")
private boolean mAddAccountCalled = false;
private AuthenticatorDescription[] mAuthDescs;
private Map<String, AuthenticatorDescription> mTypeToAuthDescription;
private ArrayList<ProviderEntry> mProviderList;
private HashMap<String, ArrayList<String>> mAccountTypeToAuthorities = null;
private Account account;
private List<Account> accountList;
private List<Account> manageAccountList;
android.accounts.Account accounts[] = null;
Object syncObserverHandle;
Object syncObserverHandle2;
Object syncObserverHandle3;
public AccountAndSyncManager() {
accountList = new ArrayList<Account>();
}
public void addAccount(String accountType) {
Log.e(Thread.currentThread().getStackTrace()[2].getLineNumber() + ". "
+ "ADD ACCOUNT", "" + accountType);
Bundle addAccountOptions = new Bundle();
mPendingIntent = PendingIntent.getBroadcast(IWEDIAService.getContext(),
0, new Intent(), 0);
addAccountOptions.putParcelable(KEY_CALLER_IDENTITY, mPendingIntent);
addAccountOptions.putBoolean(EXTRA_HAS_MULTIPLE_USERS, false);
AccountManager.get(IWEDIAService.getContext()).addAccount(accountType,
null, /* authTokenType */
null, /* requiredFeatures */
addAccountOptions, null, mCallback, null /* handler */);
mAddAccountCalled = true;
}
/**
* Updates provider icons. Subclasses should call this in onCreate() and
* update any UI that depends on AuthenticatorDescriptions in
* onAuthDescriptionsUpdated().
*/
private void typeToAuthDescription() {
mTypeToAuthDescription = new HashMap<String, AuthenticatorDescription>();
mAuthDescs = AccountManager.get(IWEDIAService.getContext())
.getAuthenticatorTypes();
for (int i = 0; i < mAuthDescs.length; i++) {
mTypeToAuthDescription.put(mAuthDescs[i].type, mAuthDescs[i]);
}
}
public List<Account> getAvailableAccounts() {
accountList = new ArrayList<Account>();
mProviderList = new ArrayList<ProviderEntry>();
typeToAuthDescription();
return onAuthDescriptionsUpdated();
}
private List<Account> onAuthDescriptionsUpdated() {
for (int i = 0; i < mAuthDescs.length; i++) {
String accountType = mAuthDescs[i].type;
CharSequence providerName = getLabelForType(accountType);
mProviderList.add(new ProviderEntry(providerName, accountType));
}
if (mProviderList.size() > 0) {
Collections.sort(mProviderList);
for (ProviderEntry pref : mProviderList) {
account = new Account();
account.setAccountLabel(pref.name.toString());
account.setAccountType(pref.type);
account.setImage(getByteArrayFromDrawable(getDrawableForType(pref.type)));
if (IWEDIAService.DEBUG)
Log.e("Account type: " + pref.type, " Account name: "
+ pref.name);
accountList.add(account);
}
} else {
if (IWEDIAService.DEBUG) {
Log.e(TAG, "No providers found.");
}
accountList.add(null);
}
return accountList;
}
List<Account> manageAccounts() {
manageAccountList = new ArrayList<Account>();
typeToAuthDescription();
accounts = AccountManager.get(IWEDIAService.getContext()).getAccounts();
for (int i = 0; i < accounts.length; i++) {
account = new Account();
account.setAccountLabel(accounts[i].name);
account.setAccountType(accounts[i].type);
account.setImage(getByteArrayFromDrawable(getDrawableForType(account
.getAccountType())));
manageAccountList.add(account);
}
if (accounts.length == 0) {
return null;
}
return manageAccountList;
}
public void setIsSyncable(Account account, String authority,
boolean isSyncable) {
int sync;
android.accounts.Account accountSync = null;
if (isSyncable) {
sync = 1;
} else {
sync = 0;
}
for (int i = 0; i < accounts.length; i++) {
if (accounts[i].name.equals(account.getAccountLabel())) {
accountSync = accounts[i];
if (IWEDIAService.DEBUG) {
Log.w("******setIsSyncable", accountSync.name);
}
break;
}
}
ContentResolver.setIsSyncable(accountSync, authority, sync);
}
public boolean getIsSyncable(Account account, String authority) {
android.accounts.Account accountSync = null;
for (int i = 0; i < accounts.length; i++) {
if (accounts[i].name.equals(account.getAccountLabel())) {
accountSync = accounts[i];
break;
}
}
int isSync = ContentResolver.getIsSyncable(accountSync, authority);
if (isSync == 0) {
return false;
} else {
return true;
}
}
public boolean getSyncStatus(Account account) {
boolean isSync = false;
if (isAutoSync()) {
ArrayList<String> authAcc = getAuthoritiesForAccountType(account
.getAccountType());
if (authAcc != null) {
for (int i = 0; i < authAcc.size(); i++) {
isSync = getIsSyncable(account, authAcc.get(i));
if (isSync) {
break;
}
}
}
return isSync;
} else {
return false;
}
}
public boolean isAutoSync() {
return ContentResolver.getMasterSyncAutomatically();
}
public void setAutoSync(boolean sync) {
ContentResolver.setMasterSyncAutomatically(sync);
}
public void syncNow(Account account, String authority) {
Log.e("Account: " + account.getAccountLabel(), "Authority: "
+ authority);
android.accounts.Account account2 = null;
if (accounts == null)
accounts = AccountManager.get(IWEDIAService.getContext())
.getAccounts();
for (int i = 0; i < accounts.length; i++) {
if (accounts[i].name.equals(account.getAccountLabel())) {
account2 = accounts[i];
break;
}
}
if (account2 != null) {
Bundle extras = new Bundle();
extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
ContentResolver.requestSync(account2, authority, extras);
}
}
public ArrayList<String> getAuthoritiesForAccountType(String type) {
if (mAccountTypeToAuthorities == null) {
mAccountTypeToAuthorities = new HashMap<String, ArrayList<String>>();
SyncAdapterType[] syncAdapters = ContentResolver
.getSyncAdapterTypes();
for (int i = 0, n = syncAdapters.length; i < n; i++) {
final SyncAdapterType sa = syncAdapters[i];
ArrayList<String> authorities = mAccountTypeToAuthorities
.get(sa.accountType);
if (authorities == null) {
authorities = new ArrayList<String>();
mAccountTypeToAuthorities.put(sa.accountType, authorities);
}
if (!sa.authority.equals("com.android.contacts")
&& !sa.authority.equals("subscribedfeeds")) {
authorities.add(sa.authority);
}
}
}
return mAccountTypeToAuthorities.get(type);
}
/**
* Gets an icon associated with a particular account type. If none found,
* return null.
*
* @param accountType
* the type of account
* @return a drawable for the icon or null if one cannot be found.
*/
protected Drawable getDrawableForType(final String accountType) {
Drawable icon = null;
if (mTypeToAuthDescription.containsKey(accountType)) {
try {
AuthenticatorDescription desc = mTypeToAuthDescription
.get(accountType);
Context authContext = IWEDIAService.getContext()
.createPackageContext(desc.packageName, 0);
icon = authContext.getResources().getDrawable(desc.iconId);
} catch (PackageManager.NameNotFoundException e) {
// TODO: place holder icon for missing account icons?
Log.w(TAG, "No icon name for account type " + accountType);
} catch (Resources.NotFoundException e) {
// TODO: place holder icon for missing account icons?
Log.w(TAG, "No icon resource for account type " + accountType);
}
}
return icon;
}
/**
* Gets the label associated with a particular account type. If none found,
* return null.
*
* @param accountType
* the type of account
* @return a CharSequence for the label or null if one cannot be found.
*/
protected CharSequence getLabelForType(final String accountType) {
CharSequence label = null;
if (mTypeToAuthDescription.containsKey(accountType)) {
try {
AuthenticatorDescription desc = mTypeToAuthDescription
.get(accountType);
Context authContext = IWEDIAService.getContext()
.createPackageContext(desc.packageName, 0);
label = authContext.getResources().getText(desc.labelId);
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "No label name for account type " + accountType);
} catch (Resources.NotFoundException e) {
Log.w(TAG, "No label resource for account type " + accountType);
}
}
return label;
}
private static class ProviderEntry implements Comparable<ProviderEntry> {
private final CharSequence name;
private final String type;
ProviderEntry(CharSequence providerName, String accountType) {
name = providerName;
type = accountType;
}
public int compareTo(ProviderEntry another) {
if (name == null) {
return -1;
}
if (another.name == null) {
return +1;
}
return name.toString().compareToIgnoreCase(another.name.toString());
}
}
private AccountManagerCallback<Bundle> mCallback = new AccountManagerCallback<Bundle>() {
public void run(AccountManagerFuture<Bundle> future) {
// boolean done = true;
try {
Bundle bundle = future.getResult();
// bundle.keySet();
Intent intent = (Intent) bundle.get(AccountManager.KEY_INTENT);
if (intent != null) {
// done = false;
Bundle addAccountOptions = new Bundle();
addAccountOptions.putParcelable(KEY_CALLER_IDENTITY,
mPendingIntent);
addAccountOptions.putBoolean(EXTRA_HAS_MULTIPLE_USERS,
false);
intent.putExtras(addAccountOptions);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (IWEDIAService.DEBUG) {
Log.e("TAG", "" + intent);
}
IWEDIAService.getInstance().startActivity(intent);
}
if (IWEDIAService.DEBUG) {
Log.e(TAG, "account added: " + bundle);
}
} catch (OperationCanceledException e) {
Log.e(TAG, "addAccount was canceled");
} catch (IOException e) {
Log.e(TAG, "addAccount failed: " + e);
} catch (AuthenticatorException e) {
Log.e(TAG, "addAccount failed: " + e);
}
}
};
public byte[] getByteArrayFromDrawable(Drawable drawable) {
if (drawable != null) {
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
return stream.toByteArray();
} else {
return null;
}
}
public static AccountAndSyncManager getInstance() {
if (instance == null) {
instance = new AccountAndSyncManager();
}
return instance;
}
public void registerObserverListeners() {
syncObserverHandle = ContentResolver.addStatusChangeListener(
ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE,
new SyncStatusObserver() {
@Override
public void onStatusChanged(int which) {
SystemControl.broadcastSyncFinishedEvent();
}
});
syncObserverHandle2 = ContentResolver.addStatusChangeListener(
ContentResolver.SYNC_OBSERVER_TYPE_PENDING,
new SyncStatusObserver() {
@Override
public void onStatusChanged(int which) {
SystemControl.broadcastSyncStartedEvent();
}
});
syncObserverHandle3 = ContentResolver.addStatusChangeListener(
ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS,
new SyncStatusObserver() {
@Override
public void onStatusChanged(int which) {
Log.e("SYNC_OBSERVER_TYPE_SETTINGS", "" + which);
}
});
}
public void unregisterObserverListeners() {
ContentResolver.removeStatusChangeListener(syncObserverHandle);
ContentResolver.removeStatusChangeListener(syncObserverHandle2);
ContentResolver.removeStatusChangeListener(syncObserverHandle3);
}
}