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 --- Android.mk | 11 +- AndroidManifest.xml | 2 +- build.gradle | 2 + libs/libGoogleFeed.jar | Bin 0 -> 24271 bytes res/values-ldrtl/config.xml | 5 + res/values/config.xml | 1 + res/values/lineage_strings.xml | 8 +- res/xml/launcher_preferences.xml | 19 +- 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 +++++++++++++++++++++ 14 files changed, 395 insertions(+), 19 deletions(-) create mode 100644 libs/libGoogleFeed.jar create mode 100644 res/values-ldrtl/config.xml 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 diff --git a/Android.mk b/Android.mk index e01d9bfde..3a6bdd721 100644 --- a/Android.mk +++ b/Android.mk @@ -16,6 +16,14 @@ LOCAL_PATH := $(call my-dir) +# +# Prebuilt Google Feed library +# +include $(CLEAR_VARS) +LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \ + libGoogleFeed:libs/libGoogleFeed.jar +include $(BUILD_MULTI_PREBUILT) + # # Build rule for Launcher3 app. # @@ -29,7 +37,8 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ android-support-v7-appcompat \ android-support-v7-recyclerview \ android-support-v7-palette \ - android-support-dynamic-animation + android-support-dynamic-animation \ + libGoogleFeed LOCAL_SRC_FILES := \ $(call all-java-files-under, src) \ diff --git a/AndroidManifest.xml b/AndroidManifest.xml index d74a88372..9f73da9be 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -70,7 +70,7 @@ attributes and intent filters the same --> + + + @string/msg_minus_one_on_left + diff --git a/res/values/config.xml b/res/values/config.xml index f87d7a839..8ae0acfd3 100644 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -154,4 +154,5 @@ + @string/msg_minus_one_on_left diff --git a/res/values/lineage_strings.xml b/res/values/lineage_strings.xml index 980de5da3..3ac2f4300 100644 --- a/res/values/lineage_strings.xml +++ b/res/values/lineage_strings.xml @@ -70,9 +70,15 @@ Force adaptive icons Icons with a custom shape will be boxed Icons with a custom shape will not be boxed - Enable feed integration Allow edit Icons and widgets can be added, removed and moved on the homescreen Icons and widgets can\'t be added, removed and moved on the homescreen It\'s not possible to add widgets to the home screen + + + Show Google App + + When you swipe left from main Home screen + + When you swipe left right main Home screen diff --git a/res/xml/launcher_preferences.xml b/res/xml/launcher_preferences.xml index e9bf50482..4d23cedf9 100644 --- a/res/xml/launcher_preferences.xml +++ b/res/xml/launcher_preferences.xml @@ -19,14 +19,21 @@ android:icon="@drawable/ic_settings_edit" android:key="pref_workspace_edit" android:persistent="true" - android:title="@string/settings_edit_allow_title" + android:summaryOff="@string/settings_edit_allow_summary_off" android:summaryOn="@string/settings_edit_allow_summary_on" - android:summaryOff="@string/settings_edit_allow_summary_off" /> + android:title="@string/settings_edit_allow_title" /> + + + android:title="@string/icon_badging_title" + android:widgetLayout="@layout/notification_pref_warning"> ()); - 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