• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.launcher3;
18 
19 import android.content.ComponentName;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.pm.PackageInfo;
23 import android.content.pm.PackageManager;
24 import android.net.Uri;
25 import android.text.TextUtils;
26 import android.util.Log;
27 import android.view.View;
28 
29 import androidx.core.content.FileProvider;
30 
31 import com.android.launcher3.model.data.ItemInfo;
32 import com.android.launcher3.popup.SystemShortcut;
33 
34 import java.io.File;
35 
36 /**
37  * Defines the Share system shortcut and its factory.
38  * This shortcut can be added to the app long-press menu on the home screen.
39  * Clicking the button will initiate peer-to-peer sharing of the app.
40  */
41 public final class AppSharing {
42     /**
43      * This flag enables this feature. It is defined here rather than in launcher3's FeatureFlags
44      * because it is unique to Go and not toggleable at runtime.
45      */
46     public static final boolean ENABLE_APP_SHARING = true;
47 
48     private static final String TAG = "AppSharing";
49     private static final String FILE_PROVIDER_SUFFIX = ".overview.fileprovider";
50     private static final String APP_EXSTENSION = ".apk";
51     private static final String APP_MIME_TYPE = "application/application";
52 
53     private final String mSharingComponent;
54 
AppSharing(Launcher launcher)55     private AppSharing(Launcher launcher) {
56         mSharingComponent = launcher.getText(R.string.app_sharing_component).toString();
57     }
58 
canShare(ItemInfo info)59     private boolean canShare(ItemInfo info) {
60         /**
61          * TODO: Implement once b/168831749 has been resolved
62          * The implementation should check the validity of the app.
63          * It should also check whether the app is free or paid, returning false in the latter case.
64          * For now, all checks occur in the sharing app.
65          * So, we simply check whether the sharing app is defined.
66          */
67         return !TextUtils.isEmpty(mSharingComponent);
68     }
69 
getShareableUri(Context context, String path, String displayName)70     private Uri getShareableUri(Context context, String path, String displayName) {
71         String authority = BuildConfig.APPLICATION_ID + FILE_PROVIDER_SUFFIX;
72         File pathFile = new File(path);
73         return FileProvider.getUriForFile(context, authority, pathFile, displayName);
74     }
75 
getShortcut(Launcher launcher, ItemInfo info)76     private SystemShortcut<Launcher> getShortcut(Launcher launcher, ItemInfo info) {
77         if (!canShare(info)) {
78             return null;
79         }
80 
81         return new Share(launcher, info);
82     }
83 
84     /**
85      * The Share App system shortcut, used to initiate p2p sharing of a given app
86      */
87     public final class Share extends SystemShortcut<Launcher> {
Share(Launcher target, ItemInfo itemInfo)88         public Share(Launcher target, ItemInfo itemInfo) {
89             super(R.drawable.ic_share, R.string.app_share_drop_target_label, target, itemInfo);
90         }
91 
92         @Override
onClick(View view)93         public void onClick(View view) {
94             Intent sendIntent = new Intent();
95             sendIntent.setAction(Intent.ACTION_SEND);
96 
97             ComponentName targetComponent = mItemInfo.getTargetComponent();
98             if (targetComponent == null) {
99                 Log.e(TAG, "Item missing target component");
100                 return;
101             }
102             String packageName = targetComponent.getPackageName();
103             PackageManager packageManager = view.getContext().getPackageManager();
104             String sourceDir, appLabel;
105             try {
106                 PackageInfo packageInfo = packageManager.getPackageInfo(packageName, 0);
107                 sourceDir = packageInfo.applicationInfo.sourceDir;
108                 appLabel = packageManager.getApplicationLabel(packageInfo.applicationInfo)
109                         .toString() + APP_EXSTENSION;
110             } catch (Exception e) {
111                 Log.e(TAG, "Could not find info for package \"" + packageName + "\"");
112                 return;
113             }
114             Uri uri = getShareableUri(view.getContext(), sourceDir, appLabel);
115             sendIntent.putExtra(Intent.EXTRA_STREAM, uri);
116             sendIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
117 
118             sendIntent.setType(APP_MIME_TYPE);
119             sendIntent.setComponent(ComponentName.unflattenFromString(mSharingComponent));
120 
121             mTarget.startActivitySafely(view, sendIntent, mItemInfo);
122 
123             AbstractFloatingView.closeAllOpenViews(mTarget);
124         }
125     }
126 
127     /**
128      * Shortcut factory for generating the Share App button
129      */
130     public static final SystemShortcut.Factory<Launcher> SHORTCUT_FACTORY = (launcher, itemInfo) ->
131             (new AppSharing(launcher)).getShortcut(launcher, itemInfo);
132 }
133