diff options
-rw-r--r-- | Android.mk | 11 | ||||
-rw-r--r-- | AndroidManifest.xml | 2 | ||||
-rw-r--r-- | build.gradle | 2 | ||||
-rw-r--r-- | libs/libGoogleFeed.jar | bin | 0 -> 24271 bytes | |||
-rw-r--r-- | res/values-ldrtl/config.xml | 5 | ||||
-rw-r--r-- | res/values/config.xml | 1 | ||||
-rw-r--r-- | res/values/lineage_strings.xml | 8 | ||||
-rw-r--r-- | res/xml/launcher_preferences.xml | 19 | ||||
-rw-r--r-- | src/com/android/launcher3/Launcher.java | 19 | ||||
-rw-r--r-- | src/com/android/launcher3/SettingsActivity.java | 7 | ||||
-rw-r--r-- | src/com/android/launcher3/Utilities.java | 9 | ||||
-rw-r--r-- | src/com/android/launcher3/searchlauncher/OverlayCallbackImpl.java | 83 | ||||
-rw-r--r-- | src/com/android/launcher3/searchlauncher/SearchLauncher.java | 26 | ||||
-rw-r--r-- | src/com/android/launcher3/searchlauncher/SearchLauncherCallbacks.java | 222 |
14 files changed, 395 insertions, 19 deletions
diff --git a/Android.mk b/Android.mk index e01d9bfde..3a6bdd721 100644 --- a/Android.mk +++ b/Android.mk @@ -17,6 +17,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. # include $(CLEAR_VARS) @@ -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 --> <activity - android:name="com.android.launcher3.Launcher" + android:name="com.android.launcher3.searchlauncher.SearchLauncher" android:launchMode="singleTask" android:clearTaskOnLaunch="true" android:stateNotNeeded="true" diff --git a/build.gradle b/build.gradle index e918ad118..38557aa40 100644 --- a/build.gradle +++ b/build.gradle @@ -103,6 +103,8 @@ repositories { final String SUPPORT_LIBS_VERSION = '27.1.1' dependencies { + implementation fileTree(dir: 'libs', include: ['libGoogleFeed.jar']) + implementation "com.android.support:appcompat-v7:${SUPPORT_LIBS_VERSION}" implementation "com.android.support:design:${SUPPORT_LIBS_VERSION}" implementation "com.android.support:palette-v7:${SUPPORT_LIBS_VERSION}" diff --git a/libs/libGoogleFeed.jar b/libs/libGoogleFeed.jar Binary files differnew file mode 100644 index 000000000..5cda956ac --- /dev/null +++ b/libs/libGoogleFeed.jar diff --git a/res/values-ldrtl/config.xml b/res/values-ldrtl/config.xml new file mode 100644 index 000000000..cd93f5459 --- /dev/null +++ b/res/values-ldrtl/config.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + + <string name="pref_show_google_now_summary" translatable="false">@string/msg_minus_one_on_left</string> +</resources> 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 @@ <item type="id" name="search_container_hotseat" /> <item type="id" name="search_container_all_apps" /> + <string name="pref_show_google_now_summary" translatable="false">@string/msg_minus_one_on_left</string> </resources> 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 @@ <string name="settings_icon_force_adaptive_title">Force adaptive icons</string> <string name="settings_icon_force_adaptive_desc_on">Icons with a custom shape will be boxed</string> <string name="settings_icon_force_adaptive_desc_off">Icons with a custom shape will not be boxed</string> - <string name="settings_feed">Enable feed integration</string> <string name="settings_edit_allow_title">Allow edit</string> <string name="settings_edit_allow_summary_on">Icons and widgets can be added, removed and moved on the homescreen</string> <string name="settings_edit_allow_summary_off">Icons and widgets can\'t be added, removed and moved on the homescreen</string> <string name="settings_edit_widgets_error">It\'s not possible to add widgets to the home screen</string> + + <!-- Settings title to show Google Now at -1 screen on launcher. [CHAR LIMIT=50] --> + <string name="title_show_google_app">Show Google App</string> + <!-- Settings message explaining when the -1 screen is available on an LTR device. [CHAR LIMIT=100] --> + <string name="msg_minus_one_on_left">When you swipe left from main Home screen</string> + <!-- Settings message explaining when the -1 screen is available on an RTL device. [CHAR LIMIT=100] --> + <string name="msg_minus_one_on_right">When you swipe left right main Home screen</string> </resources> 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,15 +19,22 @@ 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" /> <PreferenceCategory android:key="category_home" android:title="@string/settings_category_home"> <SwitchPreference + android:defaultValue="true" + android:icon="@drawable/ic_settings_feed" + android:key="pref_enable_minus_one" + android:summary="@string/pref_show_google_now_summary" + android:title="@string/title_show_google_app" /> + + <SwitchPreference android:defaultValue="@bool/allow_rotation" android:icon="@drawable/ic_settings_rotation" android:key="pref_allowRotation" @@ -95,16 +102,16 @@ android:icon="@drawable/ic_settings_force_adaptive" android:key="pref_icon_force_adaptive" android:persistent="true" - android:summaryOn="@string/settings_icon_force_adaptive_desc_on" android:summaryOff="@string/settings_icon_force_adaptive_desc_off" + android:summaryOn="@string/settings_icon_force_adaptive_desc_on" android:title="@string/settings_icon_force_adaptive_title" /> <com.android.launcher3.views.ButtonPreference + android:icon="@drawable/ic_settings_notification" android:key="pref_icon_badging" - android:title="@string/icon_badging_title" android:persistent="false" - android:icon="@drawable/ic_settings_notification" - android:widgetLayout="@layout/notification_pref_warning" > + android:title="@string/icon_badging_title" + android:widgetLayout="@layout/notification_pref_warning"> <intent android:action="android.settings.NOTIFICATION_SETTINGS"> <!-- This extra highlights the "Allow icon badges" field in Notification settings --> <extra 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<ComponentKeyMapper<AppInfo>> apps = null; + if (mSharedPrefs.getBoolean("pref_predictive_apps", true)) { + if (mLauncherCallbacks == null) { + apps = mPredictiveAppsProvider.getPredictions(); + } else { + apps = mLauncherCallbacks.getPredictedApps(); + } } - List<ComponentKeyMapper<AppInfo>> 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} + * + * <p>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<AppInfo> 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<ComponentKeyMapper<AppInfo>> 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 */ + ); + } +} |