From 0e6e432422c5c685f8878086c2c5b891cd44cf4f Mon Sep 17 00:00:00 2001 From: Adam Cohen Date: Tue, 7 Oct 2014 18:14:53 -0700 Subject: Use LauncherCallbacks model instead of method overrides -> When extending the Launcher Activity, instead of overriding public and protected methods, create a proper interface -> This helps define the interface when extending Launcher more formally and more clearly Change-Id: Ib38e8a376b2242d4078bf6856bb145f5b5f0da80 --- src/com/android/launcher3/Launcher.java | 272 +++++++++++++++++------ src/com/android/launcher3/LauncherCallbacks.java | 89 ++++++++ src/com/android/launcher3/Workspace.java | 1 - 3 files changed, 296 insertions(+), 66 deletions(-) create mode 100644 src/com/android/launcher3/LauncherCallbacks.java (limited to 'src/com/android/launcher3') diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 5b015ae29..d9f1985fe 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -501,6 +501,10 @@ public class Launcher extends Activity .build()); } + if (mLauncherCallbacks != null) { + mLauncherCallbacks.preOnCreate(); + } + super.onCreate(savedInstanceState); initializeDynamicGrid(false); @@ -579,14 +583,35 @@ public class Launcher extends Activity showFirstRunActivity(); showFirstRunClings(); } + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onCreate(savedInstanceState); + } IntentFilter protectedAppsFilter = new IntentFilter( "cyanogenmod.intent.action.PROTECTED_COMPONENT_UPDATE"); registerReceiver(protectedAppsChangedReceiver, protectedAppsFilter, "cyanogenmod.permission.PROTECTED_APP", null); } + private LauncherCallbacks mLauncherCallbacks; + + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onPostCreate(savedInstanceState); + } + } + + public boolean setLauncherCallbacks(LauncherCallbacks callbacks) { + mLauncherCallbacks = callbacks; + return true; + } + @Override - public void onLauncherProviderChange() { } + public void onLauncherProviderChange() { + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onLauncherProviderChange(); + } + } private void initializeDynamicGrid(boolean updateGrid) { if (!updateGrid) { @@ -623,8 +648,11 @@ public class Launcher extends Activity mIconCache.flushInvalidIcons(mGrid); } - /** To be overriden by subclasses to hint to Launcher that we have custom content */ + /** To be overridden by subclasses to hint to Launcher that we have custom content */ protected boolean hasCustomContentToLeft() { + if (mLauncherCallbacks != null) { + return mLauncherCallbacks.hasCustomContentToLeft(); + } return false; } @@ -634,6 +662,9 @@ public class Launcher extends Activity * {@link #hasCustomContentToLeft()} is {@code true}. */ protected void populateCustomContentContainer() { + if (mLauncherCallbacks != null) { + mLauncherCallbacks.populateCustomContentContainer(); + } } private void initializeScrubber() { @@ -1112,12 +1143,18 @@ public class Launcher extends Activity protected void onStop() { super.onStop(); FirstFrameAnimatorHelper.setIsVisible(false); + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onStop(); + } } @Override protected void onStart() { super.onStart(); FirstFrameAnimatorHelper.setIsVisible(true); + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onStart(); + } } @Override @@ -1127,6 +1164,11 @@ public class Launcher extends Activity startTime = System.currentTimeMillis(); Log.v(TAG, "Launcher.onResume()"); } + + if (mLauncherCallbacks != null) { + mLauncherCallbacks.preOnResume(); + } + super.onResume(); // Restore the previous launcher state @@ -1216,6 +1258,10 @@ public class Launcher extends Activity PackageInstallerCompat.getInstance(this).onResume(); + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onResume(); + } + //Close out Fragments TransitionEffectsFragment tef = (TransitionEffectsFragment) getFragmentManager().findFragmentByTag( @@ -1259,26 +1305,8 @@ public class Launcher extends Activity if (mWorkspace.getCustomContentCallbacks() != null) { mWorkspace.getCustomContentCallbacks().onHide(); } - } - - QSBScroller mQsbScroller = new QSBScroller() { - int scrollY = 0; - - @Override - public void setScrollY(int scroll) { - scrollY = scroll; - - if (mWorkspace.isOnOrMovingToCustomContent()) { - mSearchDropTargetBar.setTranslationY(- scrollY); - getQsbBar().setTranslationY(-scrollY); - } - } - }; - - public void resetQSBScroll() { - mSearchDropTargetBar.animate().translationY(0).start(); - if (isSearchBarEnabled()) { - getQsbBar().animate().translationY(0).start(); + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onPause(); } } @@ -1298,6 +1326,9 @@ public class Launcher extends Activity } protected boolean hasSettings() { + if (mLauncherCallbacks != null) { + return mLauncherCallbacks.hasSettings(); + } return false; } @@ -1475,14 +1506,9 @@ public class Launcher extends Activity } } - public interface QSBScroller { - public void setScrollY(int scrollY); - } - - public QSBScroller addToCustomContentPage(View customContent, + public void addToCustomContentPage(View customContent, CustomContentCallbacks callbacks, String description) { mWorkspace.addToCustomContentPage(customContent, callbacks, description); - return mQsbScroller; } // The custom content needs to offset its content to account for the QSB @@ -1507,6 +1533,10 @@ public class Launcher extends Activity public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); mHasFocus = hasFocus; + + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onWindowFocusChanged(hasFocus); + } } private boolean acceptFilter() { @@ -2074,6 +2104,7 @@ public class Launcher extends Activity // apps is nice and speedy. observer.addOnDrawListener(new ViewTreeObserver.OnDrawListener() { private boolean mStarted = false; + public void onDraw() { if (mStarted) return; mStarted = true; @@ -2085,14 +2116,14 @@ public class Launcher extends Activity mWorkspace.postDelayed(mBuildLayersRunnable, 500); final ViewTreeObserver.OnDrawListener listener = this; mWorkspace.post(new Runnable() { - public void run() { - if (mWorkspace != null && - mWorkspace.getViewTreeObserver() != null) { - mWorkspace.getViewTreeObserver(). - removeOnDrawListener(listener); - } + public void run() { + if (mWorkspace != null && + mWorkspace.getViewTreeObserver() != null) { + mWorkspace.getViewTreeObserver(). + removeOnDrawListener(listener); } - }); + } + }); return; } }); @@ -2247,8 +2278,11 @@ public class Launcher extends Activity Folder openFolder = mWorkspace.getOpenFolder(); // In all these cases, only animate if we're already on home mWorkspace.exitWidgetResizeMode(); + + boolean moveToDefaultScreen = mLauncherCallbacks != null ? + mLauncherCallbacks.shouldMoveToDefaultScreenOnHomeIntent() : true; if (alreadyOnHome && mState == State.WORKSPACE && !mWorkspace.isTouchActive() && - openFolder == null && shouldMoveToDefaultScreenOnHomeIntent()) { + openFolder == null && moveToDefaultScreen) { mWorkspace.moveToDefaultScreen(true); } @@ -2272,27 +2306,18 @@ public class Launcher extends Activity imm.hideSoftInputFromWindow(v.getWindowToken(), 0); } - onHomeIntent(); + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onHomeIntent(); + } } if (DEBUG_RESUME_TIME) { Log.d(TAG, "Time spent in onNewIntent: " + (System.currentTimeMillis() - startTime)); } - } - - /** - * Override point for subclasses to prevent movement to the default screen when the home - * button is pressed. Used (for example) in GEL, to prevent movement during a search. - */ - protected boolean shouldMoveToDefaultScreenOnHomeIntent() { - return true; - } - /** - * Override point for subclasses to provide custom behaviour for when a home intent is fired. - */ - protected void onHomeIntent() { - // Do nothing + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onNewIntent(intent); + } } @Override @@ -2344,6 +2369,10 @@ public class Launcher extends Activity outState.putInt("apps_customize_currentIndex", currentIndex); } outState.putSerializable(RUNTIME_STATE_VIEW_IDS, mItemIdToViewId); + + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onSaveInstanceState(outState); + } } @Override @@ -2394,6 +2423,10 @@ public class Launcher extends Activity PackageInstallerCompat.getInstance(this).onStop(); LauncherAnimUtils.onDestroyActivity(); + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onDestroy(); + } + unregisterReceiver(protectedAppsChangedReceiver); } @@ -2462,6 +2495,11 @@ public class Launcher extends Activity */ public boolean startSearch(String initialQuery, boolean selectInitialQuery, Bundle appSearchData, Rect sourceBounds) { + if (mLauncherCallbacks != null && mLauncherCallbacks.providesSearch()) { + return mLauncherCallbacks.startSearch(initialQuery, selectInitialQuery, appSearchData, + sourceBounds); + } + startGlobalSearch(initialQuery, selectInitialQuery, appSearchData, sourceBounds); return false; @@ -2488,7 +2526,7 @@ public class Launcher extends Activity } else { appSearchData = new Bundle(appSearchData); } - // Set source to package name of app that starts global search, if not set already. + // Set source to package name of app that starts global search if not set already. if (!appSearchData.containsKey("source")) { appSearchData.putString("source", getPackageName()); } @@ -2526,6 +2564,9 @@ public class Launcher extends Activity showWorkspace(true); } } + if (mLauncherCallbacks != null) { + return mLauncherCallbacks.onPrepareOptionsMenu(menu); + } return false; } @@ -2560,7 +2601,11 @@ public class Launcher extends Activity } } - protected void onWorkspaceLockedChanged() { } + protected void onWorkspaceLockedChanged() { + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onWorkspaceLockedChanged(); + } + } private void resetAddInfo() { mPendingAddInfo.container = ItemInfo.NO_ID; @@ -2751,6 +2796,9 @@ public class Launcher extends Activity } protected ComponentName getWallpaperPickerComponent() { + if (mLauncherCallbacks != null) { + return mLauncherCallbacks.getWallpaperPickerComponent(); + } return new ComponentName(getPackageName(), LauncherWallpaperPickerActivity.class.getName()); } @@ -2789,6 +2837,9 @@ public class Launcher extends Activity @Override public void onBackPressed() { + if (mLauncherCallbacks != null && mLauncherCallbacks.handleBackPressed()) { + return; + } Fragment f1 = getFragmentManager().findFragmentByTag( HiddenFolderFragment.HIDDEN_FOLDER_FRAGMENT); if (f1 != null) { @@ -2907,6 +2958,9 @@ public class Launcher extends Activity public void onClickPagedViewIcon(View v) { startAppShortcutOrInfoActivity(v); + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onClickPagedViewIcon(v); + } } public boolean onTouch(View v, MotionEvent event) { @@ -2968,6 +3022,10 @@ public class Launcher extends Activity } public void startVoice() { + if (mLauncherCallbacks != null && mLauncherCallbacks.providesSearch()) { + mLauncherCallbacks.startVoice(); + return; + } try { final SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); @@ -2998,6 +3056,9 @@ public class Launcher extends Activity } else { showAllApps(true, AppsCustomizePagedView.ContentType.Applications, false); } + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onClickAllAppsButton(v); + } } private void showBrokenAppInstallDialog(final String packageName, @@ -3062,6 +3123,11 @@ public class Launcher extends Activity // Start activities startAppShortcutOrInfoActivity(v); + + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onClickAppShortcut(v); + } + final ComponentName componentName = intent.getComponent(); if (componentName != null) { String packageName = componentName.getPackageName(); @@ -3173,6 +3239,9 @@ public class Launcher extends Activity } } } + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onClickFolderIcon(v); + } } /** @@ -3182,6 +3251,10 @@ public class Launcher extends Activity protected void onClickAddWidgetButton(View view) { if (LOGD) Log.d(TAG, "onClickAddWidgetButton"); showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true); + + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onClickAddWidgetButton(view); + } } /** @@ -3194,6 +3267,10 @@ public class Launcher extends Activity pickWallpaper.setComponent(getWallpaperPickerComponent()); mSharedPrefs.edit().putBoolean(LONGPRESS_CHANGE, true).apply(); startActivityForResult(pickWallpaper, REQUEST_PICK_WALLPAPER); + + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onClickWallpaperPicker(v); + } } /** @@ -3202,6 +3279,9 @@ public class Launcher extends Activity */ protected void onClickSettingsButton(View v) { if (LOGD) Log.d(TAG, "onClickSettingsButton"); + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onClickSettingsButton(v); + } } public void onTouchDownAllAppsButton(View v) { @@ -3229,13 +3309,27 @@ public class Launcher extends Activity return mHapticFeedbackTouchListener; } - public void onDragStarted(View view) {} + public void onDragStarted(View view) { + if (isOnCustomContent()) { + // Custom content screen doesn't participate in drag and drop. If on custom + // content screen, move to default. + moveWorkspaceToDefaultScreen(); + } + + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onDragStarted(view); + } + } /** * Called when the user stops interacting with the launcher. * This implies that the user is now on the homescreen and is not doing housekeeping. */ - protected void onInteractionEnd() {} + protected void onInteractionEnd() { + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onInteractionEnd(); + } + } /** * Called when the user starts interacting with the launcher. @@ -3246,7 +3340,11 @@ public class Launcher extends Activity * This is a good time to stop doing things that only make sense * when the user is on the homescreen and not doing housekeeping. */ - protected void onInteractionBegin() {} + protected void onInteractionBegin() { + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onInteractionBegin(); + } + } void startApplicationDetailsActivity(ComponentName componentName, UserHandleCompat user) { String packageName = componentName.getPackageName(); @@ -4634,6 +4732,13 @@ public class Launcher extends Activity } public View getQsbBar() { + if (mLauncherCallbacks != null) { + View qsb = mLauncherCallbacks.getQsbBar(); + if (qsb != null) { + return qsb; + } + } + if (mQsb == null) { // bind search widget if possible if (mSearchWidgetId >= 0) { @@ -4681,6 +4786,9 @@ public class Launcher extends Activity } protected boolean updateGlobalSearchIcon() { + if (mLauncherCallbacks != null && mLauncherCallbacks.providesSearch()) { + return true; + } if (mSearchWidgetId >= 0) return false; final View searchButtonContainer = findViewById(R.id.search_button_container); final ImageView searchButton = (ImageView) findViewById(R.id.search_button); @@ -4718,6 +4826,7 @@ public class Launcher extends Activity } protected void updateGlobalSearchIcon(Drawable.ConstantState d) { + if (mLauncherCallbacks != null && mLauncherCallbacks.providesSearch()) return; if (mSearchWidgetId >= 0) return; final View searchButtonContainer = findViewById(R.id.search_button_container); final View searchButton = (ImageView) findViewById(R.id.search_button); @@ -4726,6 +4835,9 @@ public class Launcher extends Activity } protected boolean updateVoiceSearchIcon(boolean searchVisible) { + if (mLauncherCallbacks != null && mLauncherCallbacks.providesSearch()) { + return true; + } if (mSearchWidgetId >= 0) return false; final View voiceButtonContainer = findViewById(R.id.voice_button_container); final View voiceButton = findViewById(R.id.voice_button); @@ -4775,6 +4887,10 @@ public class Launcher extends Activity } protected void updateVoiceSearchIcon(Drawable.ConstantState d) { + if (mLauncherCallbacks != null && mLauncherCallbacks.providesSearch()) { + return; + } + final View voiceButtonContainer = findViewById(R.id.voice_button_container); final View voiceButton = findViewById(R.id.voice_button); updateButtonWithDrawable(R.id.voice_button, d); @@ -4782,6 +4898,9 @@ public class Launcher extends Activity } public void updateVoiceButtonProxyVisible(boolean forceDisableVoiceButtonProxy) { + if (mLauncherCallbacks != null) { + forceDisableVoiceButtonProxy |= mLauncherCallbacks.forceDisableVoiceButtonProxy(); + } final View voiceButtonProxy = findViewById(R.id.voice_button_proxy); if (voiceButtonProxy != null) { boolean visible = !forceDisableVoiceButtonProxy && @@ -5342,6 +5461,11 @@ public class Launcher extends Activity mIntentsOnWorkspaceFromUpgradePath = mWorkspace.getUniqueComponents(true, null); } PackageInstallerCompat.getInstance(this).onFinishBind(); + + if (mLauncherCallbacks != null) { + mLauncherCallbacks.finishBindingItems(upgradePath); + } + mModel.recheckRestoredItems(this); mWorkspace.stripEmptyScreens(); if (mWorkspace.isInOverviewMode()) { @@ -5432,6 +5556,9 @@ public class Launcher extends Activity LauncherModel.getSortedWidgetsAndShortcuts(this)); } } + if (mLauncherCallbacks != null) { + mLauncherCallbacks.bindAllApplications(apps); + } } /** @@ -5651,16 +5778,10 @@ public class Launcher extends Activity } } - /** - * Called when the SearchBar hint should be changed. - * - * @param hint the hint to be displayed in the search bar. - */ - protected void onSearchBarHintChanged(String hint) { - - } - protected boolean isLauncherPreinstalled() { + if (mLauncherCallbacks != null) { + mLauncherCallbacks.isLauncherPreinstalled(); + } PackageManager pm = getPackageManager(); try { ApplicationInfo ai = pm.getApplicationInfo(getComponentName().getPackageName(), 0); @@ -5680,6 +5801,9 @@ public class Launcher extends Activity * when our wallpaper cropper was not yet used to set a wallpaper. */ protected boolean overrideWallpaperDimensions() { + if (mLauncherCallbacks != null) { + return mLauncherCallbacks.overrideWallpaperDimensions(); + } return true; } @@ -5713,6 +5837,9 @@ public class Launcher extends Activity * before showing the standard launcher experience. */ protected boolean hasFirstRunActivity() { + if (mLauncherCallbacks != null) { + mLauncherCallbacks.hasFirstRunActivity(); + } return false; } @@ -5720,6 +5847,9 @@ public class Launcher extends Activity * To be overridden by subclasses to launch any first run activity */ protected Intent getFirstRunActivity() { + if (mLauncherCallbacks != null) { + return mLauncherCallbacks.getFirstRunActivity(); + } return null; } @@ -5756,6 +5886,9 @@ public class Launcher extends Activity * screen that must be displayed and dismissed. */ protected boolean hasDismissableIntroScreen() { + if (mLauncherCallbacks != null) { + return mLauncherCallbacks.hasDismissableIntroScreen(); + } return false; } @@ -5763,6 +5896,9 @@ public class Launcher extends Activity * Full screen intro screen to be shown and dismissed before the launcher can be used. */ protected View getIntroScreen() { + if (mLauncherCallbacks != null) { + return mLauncherCallbacks.getIntroScreen(); + } return null; } @@ -5895,6 +6031,9 @@ public class Launcher extends Activity @Override public void onPageSwitch(View newPage, int newPageIndex) { + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onPageSwitch(newPage, newPageIndex); + } } /** @@ -5926,6 +6065,9 @@ public class Launcher extends Activity writer.println(" " + sDumpLogs.get(i)); } } + if (mLauncherCallbacks != null) { + mLauncherCallbacks.dump(prefix, fd, writer, args); + } } public static void dumpDebugLogsToConsole() { diff --git a/src/com/android/launcher3/LauncherCallbacks.java b/src/com/android/launcher3/LauncherCallbacks.java new file mode 100644 index 000000000..aef2adc7f --- /dev/null +++ b/src/com/android/launcher3/LauncherCallbacks.java @@ -0,0 +1,89 @@ +package com.android.launcher3; + +import android.content.ComponentName; +import android.content.Intent; +import android.graphics.Rect; +import android.os.Bundle; +import android.view.Menu; +import android.view.View; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.ArrayList; + +/** + * LauncherCallbacks is an interface used to extend the Launcher activity. It includes many hooks + * in order to add additional functionality. Some of these are very general, and give extending + * classes the ability to react to Activity life-cycle or specific user interactions. Others + * are more specific and relate to replacing parts of the application, for example, the search + * interface or the wallpaper picker. + */ +public interface LauncherCallbacks { + + /* + * Activity life-cycle methods. These methods are triggered after + * the code in the corresponding Launcher method is executed. + */ + public void preOnCreate(); + public void onCreate(Bundle savedInstanceState); + public void preOnResume(); + public void onResume(); + public void onStart(); + public void onStop(); + public void onPause(); + public void onDestroy(); + public void onSaveInstanceState(Bundle outState); + public void onPostCreate(Bundle savedInstanceState); + public void onNewIntent(Intent intent); + public void onActivityResult(int requestCode, int resultCode, Intent data); + public void onWindowFocusChanged(boolean hasFocus); + public boolean onPrepareOptionsMenu(Menu menu); + public void dump(String prefix, FileDescriptor fd, PrintWriter w, String[] args); + public void onHomeIntent(); + public boolean handleBackPressed(); + + /* + * Extension points for providing custom behavior on certain user interactions. + */ + public void onLauncherProviderChange(); + public void finishBindingItems(final boolean upgradePath); + public void onClickAllAppsButton(View v); + public void bindAllApplications(ArrayList apps); + public void onClickFolderIcon(View v); + public void onClickAppShortcut(View v); + public void onClickPagedViewIcon(View v); + public void onClickWallpaperPicker(View v); + public void onClickSettingsButton(View v); + public void onClickAddWidgetButton(View v); + public void onPageSwitch(View newPage, int newPageIndex); + public void onWorkspaceLockedChanged(); + public void onDragStarted(View view); + public void onInteractionBegin(); + public void onInteractionEnd(); + + /* + * Extension points for replacing the search experience + */ + public boolean forceDisableVoiceButtonProxy(); + public boolean providesSearch(); + public boolean startSearch(String initialQuery, boolean selectInitialQuery, + Bundle appSearchData, Rect sourceBounds); + public void startVoice(); + public boolean hasCustomContentToLeft(); + public void populateCustomContentContainer(); + public View getQsbBar(); + + /* + * Extensions points for adding / replacing some other aspects of the Launcher experience. + */ + public Intent getFirstRunActivity(); + public boolean hasFirstRunActivity(); + public boolean hasDismissableIntroScreen(); + public View getIntroScreen(); + public boolean shouldMoveToDefaultScreenOnHomeIntent(); + public boolean hasSettings(); + public ComponentName getWallpaperPickerComponent(); + public boolean overrideWallpaperDimensions(); + public boolean isLauncherPreinstalled(); + +} diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index f97a5a475..acb1d3965 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -1302,7 +1302,6 @@ public class Workspace extends SmoothPagedView mCustomContentShowing = false; if (mCustomContentCallbacks != null) { mCustomContentCallbacks.onHide(); - mLauncher.resetQSBScroll(); mLauncher.updateVoiceButtonProxyVisible(false); } } -- cgit v1.2.3