FileDocCategorySizeDatePackage
LandingPage.javaAPI DocAndroid 1.5 API25914Wed May 06 22:42:48 BST 2009com.android.providers.im

LandingPage

public class LandingPage extends android.app.ListActivity implements View.OnCreateContextMenuListener

Fields Summary
private static final String
TAG
private static final boolean
LOCAL_DEBUG
private static final int
ID_SIGN_IN
private static final int
ID_SIGN_OUT
private static final int
ID_EDIT_ACCOUNT
private static final int
ID_REMOVE_ACCOUNT
private static final int
ID_SIGN_OUT_ALL
private static final int
ID_ADD_ACCOUNT
private static final int
ID_VIEW_CONTACT_LIST
private static final int
ID_SETTINGS
private ProviderAdapter
mAdapter
private android.database.Cursor
mProviderCursor
private static final String[]
PROVIDER_PROJECTION
private static final int
PROVIDER_ID_COLUMN
private static final int
PROVIDER_NAME_COLUMN
private static final int
PROVIDER_FULLNAME_COLUMN
private static final int
PROVIDER_CATEGORY_COLUMN
private static final int
ACTIVE_ACCOUNT_ID_COLUMN
private static final int
ACTIVE_ACCOUNT_USERNAME_COLUMN
private static final int
ACTIVE_ACCOUNT_PW_COLUMN
private static final int
ACTIVE_ACCOUNT_LOCKED
private static final int
ACCOUNT_PRESENCE_STATUS
private static final int
ACCOUNT_CONNECTION_STATUS
private static final String
PROVIDER_SELECTION
private HashMap
mProviderToPluginMap
private HashMap
mAccountToPluginMap
private HashMap
mBrandingResources
private BrandingResources
mDefaultBrandingResources
private String[]
mProviderSelectionArgs
Constructors Summary
Methods Summary
private booleanallAccountsSignedOut()

        mProviderCursor.moveToFirst();
        do {
            if (isSignedIn(mProviderCursor)) {
                return false;
            }
        } while (mProviderCursor.moveToNext()) ;

        return true;
    
public BrandingResourcesgetBrandingResource(long providerId)

        BrandingResources res = mBrandingResources.get(providerId);
        return res == null ? mDefaultBrandingResources : res;
    
android.content.IntentgetCreateAccountIntent()

        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_INSERT);

        long providerId = mProviderCursor.getLong(PROVIDER_ID_COLUMN);
        intent.setData(ContentUris.withAppendedId(Im.Provider.CONTENT_URI, providerId));
        intent.addCategory(getProviderCategory(mProviderCursor));
        return intent;
    
android.content.IntentgetEditAccountIntent()

        Intent intent = new Intent(Intent.ACTION_EDIT,
                ContentUris.withAppendedId(Im.Account.CONTENT_URI,
                        mProviderCursor.getLong(ACTIVE_ACCOUNT_ID_COLUMN)));
        intent.addCategory(getProviderCategory(mProviderCursor));
        return intent;
    
private java.lang.StringgetProviderCategory(android.database.Cursor cursor)

        return cursor.getString(PROVIDER_CATEGORY_COLUMN);
    
private java.util.ArrayListgetSupportedProviders(android.im.IImPlugin plugin)

        ArrayList<String> providers = null;

        try {
            providers = (ArrayList<String>) plugin.getSupportedProviders();
        } catch (RemoteException ex) {
            Log.e(TAG, "getSupportedProviders caught ", ex);
        }

        return providers;
    
android.content.IntentgetViewContactsIntent()

        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(Im.Contacts.CONTENT_URI);
        intent.addCategory(getProviderCategory(mProviderCursor));
        intent.putExtra("accountId", mProviderCursor.getLong(ACTIVE_ACCOUNT_ID_COLUMN));
        return intent;
    
booleanisSignedIn(android.database.Cursor cursor)

        int connectionStatus = cursor.getInt(ACCOUNT_CONNECTION_STATUS);
        return connectionStatus == Im.ConnectionStatus.ONLINE;
    
booleanisSigningIn(android.database.Cursor cursor)

        int connectionStatus = cursor.getInt(ACCOUNT_CONNECTION_STATUS);
        return connectionStatus == Im.ConnectionStatus.CONNECTING;
    
private voidloadBrandingResources()

        mProviderCursor.moveToFirst();
        do {
            long providerId = mProviderCursor.getLong(PROVIDER_ID_COLUMN);
            String providerName = mProviderCursor.getString(PROVIDER_NAME_COLUMN);
            PluginInfo pluginInfo = mProviderToPluginMap.get(providerName);

            if (pluginInfo == null) {
                Log.w(TAG, "[LandingPage] loadBrandingResources: no plugin found for " + providerName);
                continue;
            }
            
            if (!mBrandingResources.containsKey(providerId)) {
                BrandingResources res = new BrandingResources(this, pluginInfo, providerName,
                        mDefaultBrandingResources);
                mBrandingResources.put(providerId, res);
            }
        } while (mProviderCursor.moveToNext()) ;
    
private voidloadDefaultBrandingRes()

        HashMap<Integer, Integer> resMapping = new HashMap<Integer, Integer>();

        resMapping.put(BrandingResourceIDs.DRAWABLE_LOGO, R.drawable.imlogo_s);
        resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_ONLINE,
                android.R.drawable.presence_online);
        resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_AWAY,
                android.R.drawable.presence_away);
        resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_BUSY,
                android.R.drawable.presence_busy);
        resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_INVISIBLE,
                android.R.drawable.presence_invisible);
        resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_OFFLINE,
                android.R.drawable.presence_offline);
        resMapping.put(BrandingResourceIDs.STRING_MENU_CONTACT_LIST,
                R.string.menu_view_contact_list);

        mDefaultBrandingResources = new BrandingResources(this, resMapping, null /* default res */);
    
private booleanloadPlugins()

        mProviderToPluginMap = new HashMap<String, PluginInfo>();
        
        PackageManager pm = getPackageManager();
        List<ResolveInfo> plugins = pm.queryIntentServices(
                new Intent(ImPluginConsts.PLUGIN_ACTION_NAME),
                PackageManager.GET_META_DATA);
        for (ResolveInfo info : plugins) {
            if (Log.isLoggable(TAG, Log.DEBUG)) log("loadPlugins: found plugin " + info);

            ServiceInfo serviceInfo = info.serviceInfo;
            if (serviceInfo == null) {
                Log.e(TAG, "Ignore bad IM frontdoor plugin: " + info);
                continue;
            }

            IImPlugin plugin = null;

            // Load the plug-in directly from the apk instead of binding the service
            // and calling through the IPC binder API. It's more effective in this way
            // and we can avoid the async behaviors of binding service.
            PathClassLoader classLoader = new PathClassLoader(serviceInfo.applicationInfo.sourceDir,
                    getClassLoader());
            try {
                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    log("loadPlugin: load class " + serviceInfo.name);
                }
                Class cls = classLoader.loadClass(serviceInfo.name);
                Object newInstance = cls.newInstance();
                Method m;

                // call "attach" method, so the plugin will get initialized with the proper context
                m = cls.getMethod("attach", Context.class, ActivityThread.class, String.class,
                        IBinder.class, Application.class, Object.class);
                m.invoke(newInstance,
                        new Object[] {this, null, serviceInfo.name, null, getApplication(),
                                ActivityManagerNative.getDefault()});

                // call "bind" to get the plugin object
                m = cls.getMethod("onBind", Intent.class);
                plugin = (IImPlugin)m.invoke(newInstance, new Object[]{null});
            } catch (ClassNotFoundException e) {
                Log.e(TAG, "Failed load the plugin", e);
            } catch (IllegalAccessException e) {
                Log.e(TAG, "Failed load the plugin", e);
            } catch (InstantiationException e) {
                Log.e(TAG, "Failed load the plugin", e);
            } catch (SecurityException e) {
                Log.e(TAG, "Failed load the plugin", e);
            } catch (NoSuchMethodException e) {
                Log.e(TAG, "Failed load the plugin", e);
            } catch (IllegalArgumentException e) {
                Log.e(TAG, "Failed load the plugin", e);
            } catch (InvocationTargetException e) {
                Log.e(TAG, "Failed load the plugin", e);
            }

            if (plugin != null) {
                if (Log.isLoggable(TAG, Log.DEBUG)) log("loadPlugin: plugin " + plugin + " loaded");
                ArrayList<String> providers = getSupportedProviders(plugin);

                if (providers == null || providers.size() == 0) {
                    Log.e(TAG, "Ignore bad IM frontdoor plugin: " + info + ". No providers found");
                    continue;
                }

                PluginInfo pluginInfo = new PluginInfo(plugin,
                        serviceInfo.packageName,
                        serviceInfo.name,
                        serviceInfo.applicationInfo.sourceDir);

                for (String providerName : providers) {
                    mProviderToPluginMap.put(providerName, pluginInfo);
                }
            }
        }

        return mProviderToPluginMap.size() > 0;
    
static voidlog(java.lang.String msg)

        Log.d(TAG, "[LandingPage]" + msg);
    
public booleanonContextItemSelected(android.view.MenuItem item)

        AdapterView.AdapterContextMenuInfo info;
        try {
            info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
        } catch (ClassCastException e) {
            Log.e(TAG, "bad menuInfo", e);
            return false;
        }
        long providerId = info.id;
        Cursor providerCursor = (Cursor) getListAdapter().getItem(info.position);
        long accountId = providerCursor.getLong(ACTIVE_ACCOUNT_ID_COLUMN);

        switch (item.getItemId()) {
            case ID_EDIT_ACCOUNT:
            {
                startActivity(getEditAccountIntent());
                return true;
            }

            case ID_REMOVE_ACCOUNT:
            {
                Uri accountUri = ContentUris.withAppendedId(Im.Account.CONTENT_URI, accountId);
                getContentResolver().delete(accountUri, null, null);
                // Requery the cursor to force refreshing screen
                providerCursor.requery();
                return true;
            }

            case ID_VIEW_CONTACT_LIST:
            {
                Intent intent = getViewContactsIntent();
                startActivity(intent);
                return true;
            }
            case ID_ADD_ACCOUNT:
            {
                startActivity(getCreateAccountIntent());
                return true;
            }

            case ID_SIGN_IN:
            {
                signIn(accountId);
                return true;
            }

            case ID_SIGN_OUT:
            {
                // TODO: progress bar
                signOut(accountId);
                return true;
            }

            case ID_SETTINGS:
            {
                Intent intent = new Intent(Intent.ACTION_VIEW, Im.ProviderSettings.CONTENT_URI);
                intent.addCategory(getProviderCategory(providerCursor));
                intent.putExtra("providerId", providerId);
                startActivity(intent);
                return true;
            }

        }

        return false;
    
protected voidonCreate(android.os.Bundle icicle)

        super.onCreate(icicle);

        setTitle(R.string.landing_page_title);

        if (!loadPlugins()) {
            Log.e(TAG, "[onCreate] load plugin failed, no plugin found!");
            finish();
            return;
        }

        startPlugins();

        // get everything except for Google Talk.
        mProviderSelectionArgs[0] = Im.ProviderNames.GTALK;
        mProviderCursor = managedQuery(Im.Provider.CONTENT_URI_WITH_ACCOUNT,
                PROVIDER_PROJECTION,
                PROVIDER_SELECTION /* selection */,
                mProviderSelectionArgs /* selection args */,
                Im.Provider.DEFAULT_SORT_ORDER);
        mAdapter = new ProviderAdapter(this, mProviderCursor);
        setListAdapter(mAdapter);
        
        rebuildAccountToPluginMap();

        mBrandingResources = new HashMap<Long, BrandingResources>();
        loadDefaultBrandingRes();
        loadBrandingResources();

        registerForContextMenu(getListView());
    
public voidonCreateContextMenu(android.view.ContextMenu menu, android.view.View v, android.view.ContextMenu.ContextMenuInfo menuInfo)

        AdapterView.AdapterContextMenuInfo info;
        try {
            info = (AdapterView.AdapterContextMenuInfo) menuInfo;
        } catch (ClassCastException e) {
            Log.e(TAG, "bad menuInfo", e);
            return;
        }

        Cursor providerCursor = (Cursor) getListAdapter().getItem(info.position);
        menu.setHeaderTitle(providerCursor.getString(PROVIDER_FULLNAME_COLUMN));

        if (providerCursor.isNull(ACTIVE_ACCOUNT_ID_COLUMN)) {
            menu.add(0, ID_ADD_ACCOUNT, 0, R.string.menu_add_account);
            return;
        }

        long providerId = providerCursor.getLong(PROVIDER_ID_COLUMN);
        boolean isLoggingIn = isSigningIn(providerCursor);
        boolean isLoggedIn = isSignedIn(providerCursor);

        if (!isLoggedIn) {
            menu.add(0, ID_SIGN_IN, 0, R.string.sign_in).setIcon(com.android.internal.R.drawable.ic_menu_login);
        } else {
            BrandingResources brandingRes = getBrandingResource(providerId);
            menu.add(0, ID_VIEW_CONTACT_LIST, 0,
                    brandingRes.getString(BrandingResourceIDs.STRING_MENU_CONTACT_LIST));
            menu.add(0, ID_SIGN_OUT, 0, R.string.menu_sign_out)
                .setIcon(android.R.drawable.ic_menu_close_clear_cancel);
        }

        boolean isAccountEditible = providerCursor.getInt(ACTIVE_ACCOUNT_LOCKED) == 0;
        if (isAccountEditible && !isLoggingIn && !isLoggedIn) {
            menu.add(0, ID_EDIT_ACCOUNT, 0, R.string.menu_edit_account)
                .setIcon(android.R.drawable.ic_menu_edit);
            menu.add(0, ID_REMOVE_ACCOUNT, 0, R.string.menu_remove_account)
                .setIcon(android.R.drawable.ic_menu_delete);
        }

        // always add a settings menu item
        menu.add(0, ID_SETTINGS, 0, R.string.menu_settings);
    
public booleanonCreateOptionsMenu(android.view.Menu menu)

        menu.add(0, ID_SIGN_OUT_ALL, 0, R.string.menu_sign_out_all)
                .setIcon(android.R.drawable.ic_menu_close_clear_cancel);
        return true;
    
protected voidonListItemClick(android.widget.ListView l, android.view.View v, int position, long id)

        Intent intent = null;
        mProviderCursor.moveToPosition(position);

        if (mProviderCursor.isNull(ACTIVE_ACCOUNT_ID_COLUMN)) {
            // add account
            intent = getCreateAccountIntent();
        } else {
            int state = mProviderCursor.getInt(ACCOUNT_CONNECTION_STATUS);

            if (state == Im.ConnectionStatus.OFFLINE || state == Im.ConnectionStatus.CONNECTING) {
                boolean isAccountEditible = mProviderCursor.getInt(ACTIVE_ACCOUNT_LOCKED) == 0;
                if (isAccountEditible && mProviderCursor.isNull(ACTIVE_ACCOUNT_PW_COLUMN)) {
                    // no password, edit the account
                    intent = getEditAccountIntent();
                } else {
                    long accountId = mProviderCursor.getLong(ACTIVE_ACCOUNT_ID_COLUMN);
                    signIn(accountId);
                }
            } else {
                intent = getViewContactsIntent();
            }
        }

        if (intent != null) {
            startActivity(intent);
        }
    
public booleanonOptionsItemSelected(android.view.MenuItem item)

        switch (item.getItemId()) {
            case ID_SIGN_OUT_ALL:
                signoutAll();
                return true;
        }
        return super.onOptionsItemSelected(item);
    
public booleanonPrepareOptionsMenu(android.view.Menu menu)

        super.onPrepareOptionsMenu(menu);
        menu.findItem(ID_SIGN_OUT_ALL).setVisible(!allAccountsSignedOut());
        return true;
    
protected voidonRestart()

        super.onRestart();

        // refresh the accountToPlugin map after mProviderCursor is requeried
        if (!rebuildAccountToPluginMap()) {
            Log.w(TAG, "[onRestart] rebuiltAccountToPluginMap failed, reload plugins...");
            
            if (!loadPlugins()) {
                Log.e(TAG, "[onRestart] load plugin failed, no plugin found!");
                finish();
                return;
            }
            rebuildAccountToPluginMap();
        }

        startPlugins();
    
protected voidonStop()

        super.onStop();
        stopPlugins();
    
private booleanrebuildAccountToPluginMap()

        if (Log.isLoggable(TAG, Log.DEBUG)) {
            log("rebuildAccountToPluginMap");
        }
        
        if (mAccountToPluginMap != null) {
            mAccountToPluginMap.clear();
        }
        
        mAccountToPluginMap = new HashMap<Long, PluginInfo>();

        mProviderCursor.moveToFirst();

        boolean retVal = true;

        do {
            long accountId = mProviderCursor.getLong(ACTIVE_ACCOUNT_ID_COLUMN);

            if (accountId == 0) {
                continue;
            }
            
            String name = mProviderCursor.getString(PROVIDER_NAME_COLUMN);
            PluginInfo pluginInfo = mProviderToPluginMap.get(name);
            if (pluginInfo != null) {
                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    log("rebuildAccountToPluginMap: add plugin for acct=" + accountId + ", provider=" + name);
                }
                mAccountToPluginMap.put(accountId, pluginInfo);
            } else {
                Log.w(TAG, "[LandingPage] no plugin found for " + name);
                retVal = false;
            }
        } while (mProviderCursor.moveToNext()) ;

        return retVal;
    
private voidsignIn(long accountId)

        if (accountId == 0) {
            Log.w(TAG, "signIn: account id is 0, bail");
            return;
        }

        boolean isAccountEditible = mProviderCursor.getInt(ACTIVE_ACCOUNT_LOCKED) == 0;
        if (isAccountEditible && mProviderCursor.isNull(ACTIVE_ACCOUNT_PW_COLUMN)) {
            // no password, edit the account
            if (Log.isLoggable(TAG, Log.DEBUG)) log("no pw for account " + accountId);
            Intent intent = getEditAccountIntent();
            startActivity(intent);
            return;
        }


        PluginInfo pluginInfo = mAccountToPluginMap.get(accountId);
        if (pluginInfo == null) {
            Log.e(TAG, "signIn: cannot find plugin for account " + accountId);
            return;
        }

        try {
            if (Log.isLoggable(TAG, Log.DEBUG)) log("sign in for account " + accountId);
            pluginInfo.mPlugin.signIn(accountId);
        } catch (RemoteException ex) {
            Log.e(TAG, "signIn failed", ex);
        }
    
private voidsignOut(long accountId)

        if (accountId == 0) {
            Log.w(TAG, "signOut: account id is 0, bail");
            return;
        }

        PluginInfo pluginInfo = mAccountToPluginMap.get(accountId);
        if (pluginInfo == null) {
            Log.e(TAG, "signOut: cannot find plugin for account " + accountId);
            return;
        }

        try {
            if (Log.isLoggable(TAG, Log.DEBUG)) log("sign out for account " + accountId);
            pluginInfo.mPlugin.signOut(accountId);
        } catch (RemoteException ex) {
            Log.e(TAG, "signOut failed", ex);
        }
    
private voidsignoutAll()

        do {
            long accountId = mProviderCursor.getLong(ACTIVE_ACCOUNT_ID_COLUMN);
            signOut(accountId);
        } while (mProviderCursor.moveToNext()) ;
    
private voidstartPlugins()

        Iterator<PluginInfo> itor = mProviderToPluginMap.values().iterator();

        while (itor.hasNext()) {
            PluginInfo pluginInfo = itor.next();
            try {
                pluginInfo.mPlugin.onStart();
            } catch (RemoteException e) {
                Log.e(TAG, "Could not start plugin " + pluginInfo.mPackageName, e);
            }
        }
    
private voidstopPlugins()

        Iterator<PluginInfo> itor = mProviderToPluginMap.values().iterator();

        while (itor.hasNext()) {
            PluginInfo pluginInfo = itor.next();
            try {
                pluginInfo.mPlugin.onStop();
            } catch (RemoteException e) {
                Log.e(TAG, "Could not stop plugin " + pluginInfo.mPackageName, e);
            }
        }