From a89a5084f2612f0232b2d08169a3cd05cf92a667 Mon Sep 17 00:00:00 2001 From: Jon Spivack Date: Tue, 24 Nov 2020 20:24:47 -0800 Subject: [PATCH] Add the Share App system shortcut to the Go Launcher This shortcut allows users to initiate peer-to-peer app sharing from an app's long-press menu on the home screen. It does so by passing an intent to the specified component. In this base implementation, that specification in config.xml is left blank, and the button will not appear. In GMS Launchers such as LauncherGoGoogle, the config should be set to point to Nearby Sharing. This also establishes Launcher3QuickStepGo as a distinct subclass of QuickstepLauncher instead of merely a build configuration. Bug: 157515296 Bug: 174286192 Test: Manual (tested on local wembley devices) Test: m -j RunLauncherGoGoogleRoboTests Change-Id: I826bd03721d2e7e963b15d5958e9a18a1cc16f1d --- Android.mk | 8 +- go/AndroidManifest-launcher.xml | 71 ++++++++++ go/quickstep/res/values/config.xml | 18 +++ go/quickstep/res/values/strings.xml | 6 + .../src/com/android/launcher3/AppSharing.java | 132 ++++++++++++++++++ .../launcher3/Launcher3QuickStepGo.java | 40 ++++++ .../res/xml/overview_file_provider_paths.xml | 1 + 7 files changed, 273 insertions(+), 3 deletions(-) create mode 100644 go/AndroidManifest-launcher.xml create mode 100644 go/quickstep/res/values/config.xml create mode 100644 go/quickstep/res/values/strings.xml create mode 100644 go/quickstep/src/com/android/launcher3/AppSharing.java create mode 100644 go/quickstep/src/com/android/launcher3/Launcher3QuickStepGo.java diff --git a/Android.mk b/Android.mk index 349a134d75..503f9aecb3 100644 --- a/Android.mk +++ b/Android.mk @@ -208,11 +208,13 @@ LOCAL_STATIC_ANDROID_LIBRARIES := Launcher3CommonDepsLib LOCAL_SRC_FILES := \ $(call all-java-files-under, src) \ $(call all-java-files-under, quickstep/src) \ - $(call all-java-files-under, go/src) + $(call all-java-files-under, go/src) \ + $(call all-java-files-under, go/quickstep/src) LOCAL_RESOURCE_DIR := \ $(LOCAL_PATH)/quickstep/res \ - $(LOCAL_PATH)/go/res + $(LOCAL_PATH)/go/res \ + $(LOCAL_PATH)/go/quickstep/res LOCAL_PROGUARD_FLAG_FILES := proguard.flags LOCAL_PROGUARD_ENABLED := full @@ -225,7 +227,7 @@ LOCAL_REQUIRED_MODULES := privapp_whitelist_com.android.launcher3 LOCAL_FULL_LIBS_MANIFEST_FILES := \ $(LOCAL_PATH)/go/AndroidManifest.xml \ - $(LOCAL_PATH)/quickstep/AndroidManifest-launcher.xml \ + $(LOCAL_PATH)/go/AndroidManifest-launcher.xml \ $(LOCAL_PATH)/AndroidManifest-common.xml LOCAL_MANIFEST_FILE := quickstep/AndroidManifest.xml diff --git a/go/AndroidManifest-launcher.xml b/go/AndroidManifest-launcher.xml new file mode 100644 index 0000000000..2223036a7a --- /dev/null +++ b/go/AndroidManifest-launcher.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/go/quickstep/res/values/config.xml b/go/quickstep/res/values/config.xml new file mode 100644 index 0000000000..f3767748a5 --- /dev/null +++ b/go/quickstep/res/values/config.xml @@ -0,0 +1,18 @@ + + + + + \ No newline at end of file diff --git a/go/quickstep/res/values/strings.xml b/go/quickstep/res/values/strings.xml new file mode 100644 index 0000000000..fdd8397f36 --- /dev/null +++ b/go/quickstep/res/values/strings.xml @@ -0,0 +1,6 @@ + + + + + Share App + diff --git a/go/quickstep/src/com/android/launcher3/AppSharing.java b/go/quickstep/src/com/android/launcher3/AppSharing.java new file mode 100644 index 0000000000..b72e71c2b5 --- /dev/null +++ b/go/quickstep/src/com/android/launcher3/AppSharing.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2020 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; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; + +import androidx.core.content.FileProvider; + +import com.android.launcher3.model.data.ItemInfo; +import com.android.launcher3.popup.SystemShortcut; + +import java.io.File; + +/** + * Defines the Share system shortcut and its factory. + * This shortcut can be added to the app long-press menu on the home screen. + * Clicking the button will initiate peer-to-peer sharing of the app. + */ +public final class AppSharing { + /** + * This flag enables this feature. It is defined here rather than in launcher3's FeatureFlags + * because it is unique to Go and not toggleable at runtime. + */ + public static final boolean ENABLE_APP_SHARING = true; + + private static final String TAG = "AppSharing"; + private static final String FILE_PROVIDER_SUFFIX = ".overview.fileprovider"; + private static final String APP_EXSTENSION = ".apk"; + private static final String APP_MIME_TYPE = "application/application"; + + private final String mSharingComponent; + + private AppSharing(Launcher launcher) { + mSharingComponent = launcher.getText(R.string.app_sharing_component).toString(); + } + + private boolean canShare(ItemInfo info) { + /** + * TODO: Implement once b/168831749 has been resolved + * The implementation should check the validity of the app. + * It should also check whether the app is free or paid, returning false in the latter case. + * For now, all checks occur in the sharing app. + * So, we simply check whether the sharing app is defined. + */ + return !TextUtils.isEmpty(mSharingComponent); + } + + private Uri getShareableUri(Context context, String path, String displayName) { + String authority = BuildConfig.APPLICATION_ID + FILE_PROVIDER_SUFFIX; + File pathFile = new File(path); + return FileProvider.getUriForFile(context, authority, pathFile, displayName); + } + + private SystemShortcut getShortcut(Launcher launcher, ItemInfo info) { + if (!canShare(info)) { + return null; + } + + return new Share(launcher, info); + } + + /** + * The Share App system shortcut, used to initiate p2p sharing of a given app + */ + public final class Share extends SystemShortcut { + public Share(Launcher target, ItemInfo itemInfo) { + super(R.drawable.ic_share, R.string.app_share_drop_target_label, target, itemInfo); + } + + @Override + public void onClick(View view) { + Intent sendIntent = new Intent(); + sendIntent.setAction(Intent.ACTION_SEND); + + ComponentName targetComponent = mItemInfo.getTargetComponent(); + if (targetComponent == null) { + Log.e(TAG, "Item missing target component"); + return; + } + String packageName = targetComponent.getPackageName(); + PackageManager packageManager = view.getContext().getPackageManager(); + String sourceDir, appLabel; + try { + PackageInfo packageInfo = packageManager.getPackageInfo(packageName, 0); + sourceDir = packageInfo.applicationInfo.sourceDir; + appLabel = packageManager.getApplicationLabel(packageInfo.applicationInfo) + .toString() + APP_EXSTENSION; + } catch (Exception e) { + Log.e(TAG, "Could not find info for package \"" + packageName + "\""); + return; + } + Uri uri = getShareableUri(view.getContext(), sourceDir, appLabel); + sendIntent.putExtra(Intent.EXTRA_STREAM, uri); + sendIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); + + sendIntent.setType(APP_MIME_TYPE); + sendIntent.setComponent(ComponentName.unflattenFromString(mSharingComponent)); + + mTarget.startActivitySafely(view, sendIntent, mItemInfo); + + AbstractFloatingView.closeAllOpenViews(mTarget); + } + } + + /** + * Shortcut factory for generating the Share App button + */ + public static final SystemShortcut.Factory SHORTCUT_FACTORY = (launcher, itemInfo) -> + (new AppSharing(launcher)).getShortcut(launcher, itemInfo); +} diff --git a/go/quickstep/src/com/android/launcher3/Launcher3QuickStepGo.java b/go/quickstep/src/com/android/launcher3/Launcher3QuickStepGo.java new file mode 100644 index 0000000000..8bd0fec2de --- /dev/null +++ b/go/quickstep/src/com/android/launcher3/Launcher3QuickStepGo.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 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; + +import com.android.launcher3.popup.SystemShortcut; +import com.android.launcher3.uioverrides.QuickstepLauncher; + +import java.util.stream.Stream; + +/** + * The Launcher variant used for Android Go Edition + */ +public class Launcher3QuickStepGo extends QuickstepLauncher { + private static final String TAG = "Launcher3QuickStepGo"; + + @Override + public Stream getSupportedShortcuts() { + Stream shortcuts = super.getSupportedShortcuts(); + + if (AppSharing.ENABLE_APP_SHARING) { + shortcuts = Stream.concat(shortcuts, Stream.of(AppSharing.SHORTCUT_FACTORY)); + } + + return shortcuts; + } +} diff --git a/quickstep/res/xml/overview_file_provider_paths.xml b/quickstep/res/xml/overview_file_provider_paths.xml index 14d74596e7..07e323609f 100644 --- a/quickstep/res/xml/overview_file_provider_paths.xml +++ b/quickstep/res/xml/overview_file_provider_paths.xml @@ -2,4 +2,5 @@ + \ No newline at end of file