From a77601a96c9dc0f7489e87a6ab0bb2499b8a9461 Mon Sep 17 00:00:00 2001 From: Edward Cross Date: Fri, 4 May 2018 17:36:19 +0200 Subject: Launcher3: Google Feed integration If Google Search is installed, the Google Feed can be found at the -1 screen (which is the very left). This feature is enabled by default. Change-Id: I495196818699fd378cd60e6dd61b07a0ab951762 --- src/com/android/launcher3/Launcher.java | 19 +- src/com/android/launcher3/SettingsActivity.java | 7 + src/com/android/launcher3/Utilities.java | 9 + .../searchlauncher/OverlayCallbackImpl.java | 83 ++++++++ .../launcher3/searchlauncher/SearchLauncher.java | 26 +++ .../searchlauncher/SearchLauncherCallbacks.java | 222 +++++++++++++++++++++ 6 files changed, 356 insertions(+), 10 deletions(-) create mode 100644 src/com/android/launcher3/searchlauncher/OverlayCallbackImpl.java create mode 100644 src/com/android/launcher3/searchlauncher/SearchLauncher.java create mode 100644 src/com/android/launcher3/searchlauncher/SearchLauncherCallbacks.java (limited to 'src') diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 6fbbd52fd..87b52bc27 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -3095,19 +3095,18 @@ public class Launcher extends BaseActivity * resumed. */ public void tryAndUpdatePredictedApps() { - if (!mSharedPrefs.getBoolean("pref_predictive_apps", true)) { - mAppsView.setPredictedApps(new ArrayList<>()); - return; + List> apps = null; + if (mSharedPrefs.getBoolean("pref_predictive_apps", true)) { + if (mLauncherCallbacks == null) { + apps = mPredictiveAppsProvider.getPredictions(); + } else { + apps = mLauncherCallbacks.getPredictedApps(); + } } - List> apps; - if (mLauncherCallbacks == null) { - apps = mPredictiveAppsProvider.getPredictions(); - } else { - apps = mLauncherCallbacks.getPredictedApps(); + if (apps != null) { + mAppsView.setPredictedApps(apps); } - - mAppsView.setPredictedApps(apps); } void lockAllApps() { diff --git a/src/com/android/launcher3/SettingsActivity.java b/src/com/android/launcher3/SettingsActivity.java index 63a01d122..be0712e6d 100644 --- a/src/com/android/launcher3/SettingsActivity.java +++ b/src/com/android/launcher3/SettingsActivity.java @@ -40,6 +40,7 @@ import android.provider.Settings; import com.android.launcher3.graphics.IconShapeOverride; import com.android.launcher3.notification.NotificationListener; +import com.android.launcher3.searchlauncher.SearchLauncherCallbacks; import com.android.launcher3.util.SettingsObserver; import com.android.launcher3.views.ButtonPreference; @@ -58,6 +59,7 @@ public class SettingsActivity extends Activity { private static final String KEY_SHOW_DESKTOP_LABELS = "pref_desktop_show_labels"; private static final String KEY_SHOW_DRAWER_LABELS = "pref_drawer_show_labels"; + public static final String KEY_MINUS_ONE = "pref_enable_minus_one"; static final String KEY_PREDICTIVE_APPS = "pref_predictive_apps"; public static final String KEY_WORKSPACE_EDIT = "pref_workspace_edit"; public static final String KEY_FORCE_ADAPTIVE_ICONS = "pref_icon_force_adaptive"; @@ -135,6 +137,11 @@ public class SettingsActivity extends Activity { mIconBadgingObserver.register(NOTIFICATION_BADGING, NOTIFICATION_ENABLED_LISTENERS); } + SwitchPreference minusOne = (SwitchPreference) findPreference(KEY_MINUS_ONE); + if (!Utilities.hasPackageInstalled(getContext(), + SearchLauncherCallbacks.SEARCH_PACKAGE)) { + homeGroup.removePreference(minusOne); + } SwitchPreference iconAdaptiveOverride = (SwitchPreference) findPreference(KEY_FORCE_ADAPTIVE_ICONS); diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index 2cb24ab5b..cf4cd79a5 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -747,4 +747,13 @@ public final class Utilities { SharedPreferences prefs = getPrefs(context.getApplicationContext()); return prefs.getBoolean(SettingsActivity.KEY_PREDICTIVE_APPS, false); } + + public static boolean hasPackageInstalled(Context context, String pkgName) { + try { + ApplicationInfo ai = context.getPackageManager().getApplicationInfo(pkgName, 0); + return ai.enabled; + } catch (PackageManager.NameNotFoundException e) { + return false; + } + } } diff --git a/src/com/android/launcher3/searchlauncher/OverlayCallbackImpl.java b/src/com/android/launcher3/searchlauncher/OverlayCallbackImpl.java new file mode 100644 index 000000000..796d16e83 --- /dev/null +++ b/src/com/android/launcher3/searchlauncher/OverlayCallbackImpl.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.searchlauncher; + +import com.android.launcher3.Launcher; +import com.android.launcher3.Launcher.LauncherOverlay; +import com.android.launcher3.Launcher.LauncherOverlayCallbacks; +import com.google.android.libraries.gsa.launcherclient.LauncherClient; +import com.google.android.libraries.gsa.launcherclient.LauncherClientCallbacks; + +/** + * Implements {@link LauncherOverlay} and passes all the corresponding events to {@link + * LauncherClient}. {@see setClient} + * + *

Implements {@link LauncherClientCallbacks} and sends all the corresponding callbacks to {@link + * Launcher}. + */ +public class OverlayCallbackImpl implements LauncherOverlay, LauncherClientCallbacks { + private final Launcher mLauncher; + + private LauncherClient mClient; + private LauncherOverlayCallbacks mLauncherOverlayCallbacks; + private boolean mWasOverlayAttached = false; + + public OverlayCallbackImpl(Launcher launcher) { + mLauncher = launcher; + } + + public void setClient(LauncherClient client) { + mClient = client; + } + + @Override + public void onServiceStateChanged(boolean overlayAttached, boolean hotwordActive) { + if (overlayAttached != mWasOverlayAttached) { + mWasOverlayAttached = overlayAttached; + mLauncher.setLauncherOverlay(overlayAttached ? this : null); + } + } + + @Override + public void onOverlayScrollChanged(float progress) { + if (mLauncherOverlayCallbacks != null) { + mLauncherOverlayCallbacks.onScrollChanged(progress); + } + } + + @Override + public void onScrollInteractionBegin() { + mClient.startMove(); + } + + @Override + public void onScrollInteractionEnd() { + mClient.endMove(); + } + + @Override + public void onScrollChange(float progress, boolean rtl) { + mClient.updateMove(progress); + } + + @Override + public void setOverlayCallbacks(Launcher.LauncherOverlayCallbacks callbacks) { + mLauncherOverlayCallbacks = callbacks; + } + + +} diff --git a/src/com/android/launcher3/searchlauncher/SearchLauncher.java b/src/com/android/launcher3/searchlauncher/SearchLauncher.java new file mode 100644 index 000000000..943b24573 --- /dev/null +++ b/src/com/android/launcher3/searchlauncher/SearchLauncher.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.searchlauncher; + +import com.android.launcher3.Launcher; + +public class SearchLauncher extends Launcher { + + public SearchLauncher() { + setLauncherCallbacks(new SearchLauncherCallbacks(this)); + } +} diff --git a/src/com/android/launcher3/searchlauncher/SearchLauncherCallbacks.java b/src/com/android/launcher3/searchlauncher/SearchLauncherCallbacks.java new file mode 100644 index 000000000..530f2d47d --- /dev/null +++ b/src/com/android/launcher3/searchlauncher/SearchLauncherCallbacks.java @@ -0,0 +1,222 @@ +package com.android.launcher3.searchlauncher; + +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.os.Bundle; +import android.view.Menu; +import android.view.View; + +import com.android.launcher3.AppInfo; +import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherCallbacks; +import com.android.launcher3.SettingsActivity; +import com.android.launcher3.Utilities; +import com.android.launcher3.allapps.search.AllAppsSearchBarController; +import com.android.launcher3.util.ComponentKey; +import com.android.launcher3.util.ComponentKeyMapper; +import com.google.android.libraries.gsa.launcherclient.LauncherClient; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; + +/** + * Implementation of {@link LauncherCallbacks} which integrates the Google -1 screen + * with launcher + */ +public class SearchLauncherCallbacks implements LauncherCallbacks, OnSharedPreferenceChangeListener { + public static final String SEARCH_PACKAGE = "com.google.android.googlequicksearchbox"; + + private final Launcher mLauncher; + + private OverlayCallbackImpl mOverlayCallbacks; + private LauncherClient mLauncherClient; + + private boolean mStarted; + private boolean mResumed; + private boolean mAlreadyOnHome; + + public SearchLauncherCallbacks(Launcher launcher) { + mLauncher = launcher; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + SharedPreferences prefs = Utilities.getPrefs(mLauncher); + mOverlayCallbacks = new OverlayCallbackImpl(mLauncher); + mLauncherClient = new LauncherClient(mLauncher, mOverlayCallbacks, getClientOptions(prefs)); + mOverlayCallbacks.setClient(mLauncherClient); + prefs.registerOnSharedPreferenceChangeListener(this); + } + + @Override + public void onDetachedFromWindow() { + mLauncherClient.onDetachedFromWindow(); + } + + @Override + public void onAttachedToWindow() { + mLauncherClient.onAttachedToWindow(); + } + + @Override + public void onHomeIntent() { + mLauncherClient.hideOverlay(mAlreadyOnHome); + } + + @Override + public void onResume() { + mResumed = true; + if (mStarted) { + mAlreadyOnHome = true; + } + mLauncherClient.onResume(); + } + + @Override + public void onPause() { + mResumed = false; + mLauncherClient.onPause(); + } + + @Override + public void onStart() { + mStarted = true; + mLauncherClient.onStart(); + } + + @Override + public void onStop() { + mStarted = false; + if (!mResumed) { + mAlreadyOnHome = false; + } + mLauncherClient.onStop(); + } + + @Override + public void onDestroy() { + mLauncherClient.onDestroy(); + Utilities.getPrefs(mLauncher).unregisterOnSharedPreferenceChangeListener(this); + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { + if (SettingsActivity.KEY_MINUS_ONE.equals(key)) { + mLauncherClient.setClientOptions(getClientOptions(prefs)); + } + } + + @Override + public void preOnCreate() { } + + @Override + public void preOnResume() { } + + @Override + public void onSaveInstanceState(Bundle outState) { } + + @Override + public void onPostCreate(Bundle savedInstanceState) { } + + @Override + public void onNewIntent(Intent intent) { } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { } + + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { } + + @Override + public void onWindowFocusChanged(boolean hasFocus) { } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + return false; + } + + @Override + public void dump(String prefix, FileDescriptor fd, PrintWriter w, String[] args) { } + + @Override + public boolean handleBackPressed() { + return false; + } + + @Override + public void onTrimMemory(int level) { } + + @Override + public void onLauncherProviderChange() { } + + @Override + public void finishBindingItems(boolean upgradePath) { } + + @Override + public void bindAllApplications(ArrayList apps) { } + + @Override + public void onWorkspaceLockedChanged() { } + + @Override + public void onInteractionBegin() { } + + @Override + public void onInteractionEnd() { } + + @Override + public boolean hasCustomContentToLeft() { + return false; + } + + @Override + public void populateCustomContentContainer() { } + + @Override + public View getQsbBar() { + return null; + } + + @Override + public Bundle getAdditionalSearchWidgetOptions() { + return new Bundle(); + } + + @Override + public boolean shouldMoveToDefaultScreenOnHomeIntent() { + return false; + } + + @Override + public boolean hasSettings() { + return true; + } + + @Override + public List> getPredictedApps() { + return null; + } + + @Override + public int getSearchBarHeight() { + return SEARCH_BAR_HEIGHT_NORMAL; + } + + @Override + public boolean startSearch(String initialQuery, boolean selectInitialQuery, Bundle appSearchData) { + return false; + } + + private LauncherClient.ClientOptions getClientOptions(SharedPreferences prefs) { + boolean hasPackage = Utilities.hasPackageInstalled(mLauncher, SEARCH_PACKAGE); + boolean isEnabled = prefs.getBoolean(SettingsActivity.KEY_MINUS_ONE, true); + + return new LauncherClient.ClientOptions(hasPackage && isEnabled, + true, /* enableHotword */ + true /* enablePrewarming */ + ); + } +} -- cgit v1.2.3