/* * Funambol is a mobile platform developed by Funambol, Inc. * Copyright (C) 2009 Funambol, Inc. * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License version 3 as published by * the Free Software Foundation with the addition of the following permission * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE * WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU Affero General Public License * along with this program; if not, see http://www.gnu.org/licenses or write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA. * * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com. * * The interactive user interfaces in modified source and object code versions * of this program must display Appropriate Legal Notices, as required under * Section 5 of the GNU Affero General Public License version 3. * * In accordance with Section 7(b) of the GNU Affero General Public License * version 3, these Appropriate Legal Notices must retain the display of the * "Powered by Funambol" logo. If the display of the logo is not reasonably * feasible for technical reasons, the Appropriate Legal Notices must display * the words "Powered by Funambol". */ package de.chbosync.android.syncmlclient.activities; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.content.pm.ActivityInfo; import android.os.Bundle; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnFocusChangeListener; import android.view.ViewGroup.LayoutParams; import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.Button; import android.widget.LinearLayout; import com.funambol.client.controller.Controller; import com.funambol.client.controller.HomeScreenController; import com.funambol.client.controller.UISyncSourceController; import com.funambol.client.customization.Customization; import com.funambol.client.localization.Localization; import com.funambol.client.source.AppSyncSource; import com.funambol.client.ui.Bitmap; import com.funambol.client.ui.DisplayManager; import com.funambol.client.ui.HomeScreen; import com.funambol.client.ui.UISyncSourceContainer; import com.funambol.util.Log; import de.chbosync.android.syncmlclient.AndroidAppSyncSourceManager; import de.chbosync.android.syncmlclient.AndroidConfiguration; import de.chbosync.android.syncmlclient.App; import de.chbosync.android.syncmlclient.AppInitializer; import de.chbosync.android.syncmlclient.R; import de.chbosync.android.syncmlclient.controller.AndroidHomeScreenController; import de.chbosync.android.syncmlclient.source.pim.note.OINoteManager; import de.chbosync.android.syncmlclient.source.pim.note.OINotepadInstallationHelper; /** * Activity for presenting the main screen of the app, i.e. the screen with the * buttons to trigger the syncing of individual syncing sources (e.g., calendar, notes). * Class contains several inner classes. */ public class AndroidHomeScreen extends Activity implements HomeScreen, UISyncSourceContainer { private static final String TAG = "AndroidHomeScreen"; private static final String FIRST_SYNC_ALERT_PENDING = "FirstSyncAlertPending"; private static final String WIFI_NOT_AVAILABLE_ALERT_PENDING = "WifiNotAvailableAlertPending"; // some constants for the options menu private static final int MENU_ITEM_SETTINGS_ID = Menu.FIRST; private static final int MENU_ITEM_LOGOUT_ID = MENU_ITEM_SETTINGS_ID + 1; private static final int MENU_ITEM_ABOUT_ID = MENU_ITEM_LOGOUT_ID + 1; //private static final int MENU_ITEM_REFRESH_ID = MENU_ITEM_ABOUT_ID + 1; private final int SYNC_SOURCE_ID = Menu.FIRST; private final int GOTO_SOURCE_ID = SYNC_SOURCE_ID + 1; private final int SETTINGS_SOURCE_ID = GOTO_SOURCE_ID + 1; private final int CANCEL_SOURCE_ID = SETTINGS_SOURCE_ID + 1; private AndroidHomeScreenController homeScreenController; private List<AndroidUISyncSource> listItems = new ArrayList<AndroidUISyncSource>(); private Localization localization; private Customization customization; private AndroidAppSyncSourceManager appSyncSourceManager; private AndroidDisplayManager dm; private Button syncAllButton; private LinearLayout mainLayout; private LinearLayout linLayoutForButtons; private String syncAllText = null; private SetSyncAllTextUIThread setSyncAllTextUIThread = new SetSyncAllTextUIThread(); private SetSyncAllEnabledUIThread setSyncAllEnabledUIThread = new SetSyncAllEnabledUIThread(); private RedrawUIThread redrawUIThread = new RedrawUIThread(); private UpdateAvailableSourcesUIThread updateAvailableSourcesUIThread = new UpdateAvailableSourcesUIThread(this); // This is the sync item menu entry. It is global because we need to // dynamically change its label, depending on the sync status private String syncItemText; private boolean screenLocked = false; // Changed for ChBoSync: Local variable of onCreate() method was made a member variable protected AndroidConfiguration configuration = null; /** * Called with the activity is first created. */ @Override public void onCreate(Bundle icicle) { // Set up the activity super.onCreate(icicle); // Lock the screen orientation to vertical for this screen this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); AppInitializer initializer = App.i().getAppInitializer(); initializer.init(this); // Initialize the localization localization = initializer.getLocalization(); // By default we set the multi buttons layout setMultiButtonsLayout(); // Now initialize everything customization = initializer.getCustomization(); configuration = initializer.getConfiguration(); appSyncSourceManager = initializer.getAppSyncSourceManager(); Controller controller = initializer.getController(); homeScreenController = (AndroidHomeScreenController)controller.getHomeScreenController(); homeScreenController.setHomeScreen(this); this.dm = (AndroidDisplayManager) controller.getDisplayManager(); // We have to explicitely call the initialize here initialize(homeScreenController); // Refresh the set of available sources homeScreenController.updateEnabledSources(); homeScreenController.selectFirstAvailable(); homeScreenController.attachToRunningSyncIfAny(); int firstSyncAlertId = 0; int wifiNotAvailableId = 1; if (icicle != null) { firstSyncAlertId = icicle.getInt(FIRST_SYNC_ALERT_PENDING); wifiNotAvailableId = icicle.getInt(WIFI_NOT_AVAILABLE_ALERT_PENDING); } if (firstSyncAlertId == DisplayManager.FIRST_SYNC_DIALOG_ID) { if (Log.isLoggable(Log.INFO)) { Log.info(TAG, "Removing bundle property and displaying alert after rotation"); } icicle.remove(FIRST_SYNC_ALERT_PENDING); //Resume the last sync dialog alert if it was displayed before //resuming this activity controller.getDialogController().resumeLastFirstSyncDialog(this); } else if(wifiNotAvailableId == DisplayManager.NO_WIFI_AVAILABLE_ID) { if (Log.isLoggable(Log.INFO)) { Log.info(TAG, "Removing bundle property and displaying alert after rotation"); } icicle.remove(WIFI_NOT_AVAILABLE_ALERT_PENDING); //Resume the WI-FI not available dialog alert if it was displayed before //resuming this activity controller.getDialogController().resumeWifiNotAvailableDialog(this); } else { // We shall remove all pending alerts here, in the case the app was // closed and restarted dm.removePendingAlert(DisplayManager.FIRST_SYNC_DIALOG_ID); // There is another case we must handle. The application (UI) was closed but a // automatic sync triggered the first sync dialog. In this case we // don't have anything in the activity state, but we need to show // the alert homeScreenController.showPendingFirstSyncQuestion(); } // If during the upgrade some source was disabled because its sync type // is no longer supported, then we shall inform the user if (Log.isLoggable(Log.INFO)) { Log.info(TAG, "source sync type changed = " + configuration.getPimSourceSyncTypeChanged()); } if (configuration.getPimSourceSyncTypeChanged()) { dm.showOkDialog(this, localization.getLanguage("upg_one_way_no_longer_supported"), localization.getLanguage("dialog_ok")); configuration.setPimSourceSyncTypeChanged(false); configuration.commit(); } } @Override public void onConfigurationChanged(android.content.res.Configuration newConfig) { // Do not change anything super.onConfigurationChanged(newConfig); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); if (dm.isAlertPending(DisplayManager.FIRST_SYNC_DIALOG_ID)) { dm.dismissSelectionDialog(DisplayManager.FIRST_SYNC_DIALOG_ID); outState.putInt(FIRST_SYNC_ALERT_PENDING, DisplayManager.FIRST_SYNC_DIALOG_ID); } else if (dm.isAlertPending(DisplayManager.NO_WIFI_AVAILABLE_ID)) { dm.dismissSelectionDialog(DisplayManager.NO_WIFI_AVAILABLE_ID); outState.putInt(WIFI_NOT_AVAILABLE_ALERT_PENDING, DisplayManager.NO_WIFI_AVAILABLE_ID); } } @Override protected Dialog onCreateDialog(int id) { if (Log.isLoggable(Log.TRACE)) { Log.trace(TAG, "onCreateDialog: " + id); } Dialog result = null; if(dm != null) { result = dm.createDialog(id); } if(result != null) { return result; } else { return super.onCreateDialog(id); } } @Override public void onDestroy() { super.onDestroy(); if (Log.isLoggable(Log.DEBUG)) { Log.debug(TAG, "Nullifying home screen controller reference"); } homeScreenController.setHomeScreen(null); } /** Create the Activity menu. */ @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); if (syncItemText == null) { syncItemText = localization.getLanguage("menu_sync"); } MenuItem settingsItem = menu.add(0, MENU_ITEM_SETTINGS_ID, Menu.NONE, localization.getLanguage("menu_settings")); settingsItem.setIcon(android.R.drawable.ic_menu_preferences); MenuItem logoutItem = menu.add(0, MENU_ITEM_LOGOUT_ID, Menu.NONE, localization.getLanguage("menu_logout")); logoutItem.setIcon(R.drawable.ic_menu_logout); MenuItem aboutItem = menu.add(0, MENU_ITEM_ABOUT_ID, Menu.NONE, localization.getLanguage("menu_about")); aboutItem.setShortcut('0', 'A'); aboutItem.setIcon(android.R.drawable.ic_menu_info_details); return true; } @Override public boolean onPrepareOptionsMenu(Menu menu) { return super.onPrepareOptionsMenu(menu); } @Override protected void onPause() { super.onPause(); homeScreenController.setForegroundStatus(false); Log.trace(TAG, "Paused activity (foreground status off)"); } @Override protected void onResume() { super.onResume(); homeScreenController.setForegroundStatus(true); Log.trace(TAG, "Resumed activity (foreground status on)"); } /** * Event-Handler for the option menu items */ @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle all of the possible menu actions switch ( item.getItemId() ) { case MENU_ITEM_SETTINGS_ID: homeScreenController.showConfigurationScreen(); break; case MENU_ITEM_LOGOUT_ID: showConfirmQuestionLogout(); break; case MENU_ITEM_ABOUT_ID: homeScreenController.showAboutScreen(); break; } return super.onOptionsItemSelected(item); } /** * Method shows dialog with confirmation question asking the user if he really wants to log out. * Added for CboSync */ protected void showConfirmQuestionLogout() { AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this); dialogBuilder.setTitle ( R.string.dialog_title_confirm_logout ); dialogBuilder.setMessage( R.string.dialog_confirm_logout_question ); final DialogInterface.OnClickListener onYesButtonHandler = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { homeScreenController.logout(); } }; dialogBuilder.setPositiveButton( R.string.button_yes, onYesButtonHandler ); dialogBuilder.setNegativeButton( R.string.button_no, null ); AlertDialog dialog = dialogBuilder.create(); dialog.show(); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); v.requestFocus(); AppSyncSource appSource = appSyncSourceManager.getSource(v.getId()); createContextMenuForSource(appSource, menu); } public void createContextMenuForSource(AppSyncSource appSource, ContextMenu menu) { if (appSource != null) { if (!appSource.isEnabled() || !appSource.isWorking()) { // If we get a requirement to allow sources to be enabled via // context menu, this can be done here return; } if (homeScreenController.isSynchronizing()) { // If a sync is in progress, the context menu can only be used // to stop the current sync of the current source AppSyncSource currentSource = homeScreenController.getCurrentSource(); if (currentSource != null && currentSource.getId() == appSource.getId()) { int cancelId = appSource.getId() << 16 | CANCEL_SOURCE_ID; menu.add(0, cancelId, 0, localization.getLanguage("menu_cancel_sync")); } } else { // This works if the number of sources is < 16 which is a fairly // safe assumption int syncId = appSource.getId() << 16 | SYNC_SOURCE_ID; int gotoId = appSource.getId() << 16 | GOTO_SOURCE_ID; int settingsId = appSource.getId() << 16 | SETTINGS_SOURCE_ID; StringBuffer label = new StringBuffer(); label.append(localization.getLanguage("menu_sync")).append(" ").append(appSource.getName()); menu.add(0, syncId, 0, label.toString()); // Add goto menu option only if an external app manager is set if(appSource.getAppManager() != null) { label = new StringBuffer(); label.append(localization.getLanguage("menu_goto")).append(" ").append(appSource.getName()); menu.add(0, gotoId, 0, label.toString()); } menu.add(0, settingsId, 0, localization.getLanguage("menu_settings")); } } } @Override public boolean onContextItemSelected(MenuItem item) { AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); int id = item.getItemId(); int sourceId = id >> 16; int itemId = id & 0xFFFF; AppSyncSource appSource = appSyncSourceManager.getSource(sourceId); if (appSource == null) { Log.error(TAG, "Cannot find view associated to this context menu"); return super.onContextItemSelected(item); } switch (itemId) { case SYNC_SOURCE_ID: homeScreenController.syncMenuSelected(); return true; case GOTO_SOURCE_ID: homeScreenController.gotoMenuSelected(); return true; case SETTINGS_SOURCE_ID: homeScreenController.showConfigurationScreen(); return true; case CANCEL_SOURCE_ID: homeScreenController.cancelMenuSelected(); return true; default: Log.error(TAG, "Unknwon context menu id " + id); return super.onContextItemSelected(item); } } /**************** Home Screen Implementation **********************/ public void initialize(HomeScreenController controller) { if (Log.isLoggable(Log.INFO)) { Log.info(TAG, "Initializing"); } // We force the controller to recompute the available sources homeScreenController.updateAvailableSources(); homeScreenController.redraw(); // Now update the list of visible items in the UI updateVisibleItems(); } public void lock() { screenLocked = true; } public void unlock() { screenLocked = false; } public boolean isLocked() { return screenLocked; } public void setSelectedIndex(int index) { // We can receive events before the list is actually populated. Just // ignore them if (listItems.isEmpty()) { return; } AndroidUISyncSource button = listItems.get(index); // Show the given element as selected button.setSelection(true, false); button.requestFocus(); } public void deselectIndex(int index) { // We can receive events before the list is actually populated. Just // ignore them if (listItems.isEmpty()) { return; } AndroidUISyncSource button = listItems.get(index); // Show the given element as selected button.setSelected(false); } public void redraw() { runOnUiThread(redrawUIThread); } public void updateVisibleItems() { runOnUiThread(updateAvailableSourcesUIThread); } ////////////////////////////////////////////////////////////////////// public Object getUiScreen() { return this; } private void setMultiButtonsLayout() { // Set the content view setContentView(R.layout.homescreen); // Grab the views mainLayout = (LinearLayout)findViewById(R.id.mainLayout); linLayoutForButtons = (LinearLayout)findViewById(R.id.buttons); syncAllButton = (Button)findViewById(R.id.syncAllButton); // Add the sync all button if required if (syncAllText != null) { syncAllButton.setFocusable(false); syncAllButton.setText(syncAllText); SyncAllButtonListener buttonListener = new SyncAllButtonListener(); syncAllButton.setOnClickListener(buttonListener); } else { // Remove the button bar LinearLayout buttonBar = (LinearLayout)findViewById(R.id.homeScreenButtonBar); mainLayout.removeView(buttonBar); } } private void setSingleButtonLayout() { setContentView(R.layout.homescreen_single); mainLayout = (LinearLayout)findViewById(R.id.mainLayoutSingle); linLayoutForButtons = mainLayout; syncAllButton = null; } /** * Inner class */ private class ButtonListener implements OnClickListener { private int idx; public ButtonListener(int idx) { this.idx = idx; } /** * Method for event-handling when on one of the buttons for syncing (e.g. for syncing notes) * is pressed. */ public void onClick(View view) { if (Log.isLoggable(Log.DEBUG)) { Log.debug(TAG, "Clicked on item: " + idx + " hasFocus=" + view.hasFocus()); } if (screenLocked == false) { view.requestFocus(); homeScreenController.buttonPressed(idx); } } } /** * Inner class */ private class SyncAllButtonListener implements OnClickListener { public SyncAllButtonListener() { } public void onClick(View v) { if (Log.isLoggable(Log.DEBUG)) { Log.debug(TAG, "Clicked on sync all"); } homeScreenController.syncAllPressed(); } } /** * Inner class */ private class AloneButtonListener implements OnClickListener { public AloneButtonListener() { } public void onClick(View v) { if (Log.isLoggable(Log.DEBUG)) { Log.debug(TAG, "Clicked on the alone source"); } homeScreenController.aloneSourcePressed(); } } /** * Inner class. A call-back for when the sync buttons focus changes. */ private class FocusListener implements OnFocusChangeListener { private int idx; public FocusListener(int idx) { this.idx = idx; } public void onFocusChange(View v, boolean hasFocus) { if (Log.isLoggable(Log.DEBUG)) { Log.debug(TAG, "Focus moved to item: " + idx); } if (!screenLocked && hasFocus) { homeScreenController.buttonSelected(idx); } } } public void addSyncAllButton(String text, Bitmap icon, Bitmap bg, Bitmap bgSel) { // We ignore the icons because on Android we keep the button very // simple, just text syncAllText = text; } public void setSyncAllText(String text) { setSyncAllTextUIThread.setText(text); runOnUiThread(setSyncAllTextUIThread); } public String getSyncAllText() { if (syncAllButton != null) { return syncAllButton.getText().toString(); } else { return null; } } public void setSyncAllEnabled(boolean enabled) { setSyncAllEnabledUIThread.setEnabled(enabled); runOnUiThread(setSyncAllEnabledUIThread); } public void setSyncAllSelected(boolean selected) { // Ignore this because in this view the button is separate from the // sources list } public void setSyncMenuText(String text) { syncItemText = text; } /** * Inner class */ private class RedrawUIThread implements Runnable { public RedrawUIThread() { } public void run() { mainLayout.invalidate(); } } /** * Inner class */ private class SetSyncAllTextUIThread implements Runnable { private String text; public SetSyncAllTextUIThread() { } public void setText(String text) { this.text = text; } public void run() { if (syncAllButton != null) { syncAllButton.setText(text); } } } /** * Inner class */ private class SetSyncAllEnabledUIThread implements Runnable { private boolean enabled; public SetSyncAllEnabledUIThread() { } public void setEnabled(boolean enabled) { this.enabled = enabled; } public void run() { if (syncAllButton != null) { syncAllButton.setClickable(enabled); } } } /** * Inner class, adds individual buttons (for different syncSources) * to linear layout. */ private class UpdateAvailableSourcesUIThread implements Runnable { private AndroidHomeScreen screen; public UpdateAvailableSourcesUIThread(AndroidHomeScreen screen) { this.screen = screen; } public void run() { if (homeScreenController == null) { return; } LinearLayout.LayoutParams linLayoutParams = null; // Remove all buttons first linLayoutForButtons.removeAllViews(); // Initialize the sources listed List<AppSyncSource> appSources = AndroidHomeScreen.this.homeScreenController.getVisibleItems(); Iterator<AppSyncSource> iter = appSources.iterator(); int idx = 0; while( iter.hasNext() ) { AppSyncSource appSource = iter.next(); UISyncSourceController itemController; itemController = appSource.getUISyncSourceController(); // Prepare the source icon to be displayed Bitmap sourceIcon = null; if ( appSource.isWorking() && appSource.isEnabled() ) { sourceIcon = customization.getSourceIcon(appSource.getId()); } else { sourceIcon = customization.getSourceDisabledIcon(appSource.getId()); } // Create an item for each entry, if there is only one entry, // then we build a stand alone representation AndroidUISyncSource item = null; if (idx == 0 && !iter.hasNext()) { // The source is alone item = (AndroidUISyncSource)appSource.createAloneUISyncSource(screen); if (item != null) { // Change the overall layout setSingleButtonLayout(); // Remove the sync all button linLayoutParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); int margin = adaptSizeToDensity(10); linLayoutParams.setMargins(0, 0, 0, margin); // bottom=margin // Disable the status animation supplied by the controller itemController.disableStatusAnimation(); // Set localization and customization if (item instanceof AndroidAloneUISyncSource) { AndroidAloneUISyncSource aloneItem = (AndroidAloneUISyncSource)item; aloneItem.setLocalization(localization); aloneItem.setCustomization(customization); aloneItem.setHomeScreenView(AndroidHomeScreen.this); } // Register the button listener AloneButtonListener buttonListener = new AloneButtonListener(); item.setOnClickListener(buttonListener); } } if (item == null) { if (idx == 0) { setMultiButtonsLayout(); } item = (AndroidUISyncSource)appSource.createButtonUISyncSource(screen); // The buttons shall only wrap the content linLayoutParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); int margin = adaptSizeToDensity(2); linLayoutParams.setMargins(margin, margin, margin, margin); // Enable the status animation supplied by the controller itemController.enableStatusAnimation(); // Register the button listener ButtonListener buttonListener = new ButtonListener(idx); item.setOnClickListener(buttonListener); } item.setSource(appSource); itemController.setUISyncSource(item); // All these buttons are associated to a given application // source item.setSource(appSource); item.setContainer(screen); if (sourceIcon != null) { item.setIcon(sourceIcon); } item.setTitle(appSource.getName()); listItems.add(item); // Add this button to the main list and the appropriate listeners FocusListener focusListener = new FocusListener(idx); item.setOnFocusChangeListener(focusListener); // We use the app source id as view id so we can quickly recognize // it in the context menu handling item.setId(appSource.getId()); registerForContextMenu(item); linLayoutForButtons.addView(item, linLayoutParams); idx++; } // If "OI Notepad" is not installed then display button for installation of this app if (configuration.getShowDummyButtonForNotesSyncing() && OINoteManager.getOINotepadInstalled() == false) { LinearLayout.LayoutParams linLayoutParams2 = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); int margin = adaptSizeToDensity(20); // add a bigger gap to indicate that now another type of buttons is comming linLayoutParams2.setMargins(0, margin, 0, 0); // top=margin linLayoutForButtons.addView( createSyncingNotesDisabledButton(), linLayoutParams2); } } // run() } // end of inner class /** * Creates a Dummy-Sync-Button for notes when "OI Notepad" is not installed. * This button gets also an event-handler for trying to install "OI Notepad". * Added for ChBoSync * * @return UI-Element to be added when syncing of notes is disabled. */ protected View createSyncingNotesDisabledButton() { AndroidButtonUISyncSource notesDisabledButton = new AndroidButtonUISyncSource(AndroidHomeScreen.this); notesDisabledButton.setTitle( getString(R.string.syncing_notes_disabled) ); notesDisabledButton.setStatusString( "Click here to install \"OI Notepad\"" ); notesDisabledButton.setIcon(new Bitmap(R.drawable.icon_notes_grey)); notesDisabledButton.setStatusIcon(new Bitmap(R.drawable.icon_notes_grey)); notesDisabledButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { if ( OINotepadInstallationHelper.isIntentToOpenAppStoreClientSupported(AndroidHomeScreen.this) == true ) { OINotepadInstallationHelper.showDialog_ConfirmQuestionGoToAppstoreClient(AndroidHomeScreen.this); } else { OINotepadInstallationHelper.showDialog_AppstoreClientNotAvailable(AndroidHomeScreen.this); } } }); return notesDisabledButton; } private int adaptSizeToDensity(int size) { return (int)(size*getResources().getDisplayMetrics().density); } }