OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser.share; | 5 package org.chromium.chrome.browser.share; |
6 | 6 |
7 import android.app.Activity; | 7 import android.app.Activity; |
8 import android.app.AlertDialog; | 8 import android.app.AlertDialog; |
9 import android.content.ComponentName; | 9 import android.content.ComponentName; |
10 import android.content.Context; | 10 import android.content.Context; |
11 import android.content.Intent; | 11 import android.content.Intent; |
12 import android.content.SharedPreferences; | 12 import android.content.SharedPreferences; |
13 import android.content.pm.ActivityInfo; | 13 import android.content.pm.ActivityInfo; |
14 import android.content.pm.ApplicationInfo; | 14 import android.content.pm.ApplicationInfo; |
15 import android.content.pm.PackageManager; | 15 import android.content.pm.PackageManager; |
16 import android.content.pm.PackageManager.NameNotFoundException; | 16 import android.content.pm.PackageManager.NameNotFoundException; |
17 import android.content.pm.ResolveInfo; | 17 import android.content.pm.ResolveInfo; |
18 import android.graphics.Bitmap; | 18 import android.graphics.Bitmap; |
19 import android.graphics.drawable.Drawable; | 19 import android.graphics.drawable.Drawable; |
| 20 import android.os.AsyncTask; |
20 import android.preference.PreferenceManager; | 21 import android.preference.PreferenceManager; |
| 22 import android.util.Log; |
21 import android.view.MenuItem; | 23 import android.view.MenuItem; |
22 import android.view.View; | 24 import android.view.View; |
23 import android.widget.AdapterView; | 25 import android.widget.AdapterView; |
24 import android.widget.AdapterView.OnItemClickListener; | 26 import android.widget.AdapterView.OnItemClickListener; |
25 | 27 |
26 import org.chromium.base.ApiCompatibilityUtils; | 28 import org.chromium.base.ApiCompatibilityUtils; |
| 29 import org.chromium.base.ApplicationState; |
| 30 import org.chromium.base.ApplicationStatus; |
27 import org.chromium.base.VisibleForTesting; | 31 import org.chromium.base.VisibleForTesting; |
28 import org.chromium.chrome.R; | 32 import org.chromium.chrome.R; |
29 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; | 33 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; |
| 34 import org.chromium.ui.UiUtils; |
30 | 35 |
| 36 import java.io.File; |
| 37 import java.io.FileOutputStream; |
| 38 import java.io.IOException; |
31 import java.util.Collections; | 39 import java.util.Collections; |
32 import java.util.List; | 40 import java.util.List; |
33 | 41 |
34 /** | 42 /** |
35 * A helper class that helps to start an intent to share titles and URLs. | 43 * A helper class that helps to start an intent to share titles and URLs. |
36 */ | 44 */ |
37 public class ShareHelper { | 45 public class ShareHelper { |
38 | 46 |
| 47 private static final String TAG = "ShareHelper"; |
| 48 |
39 private static final String PACKAGE_NAME_KEY = "last_shared_package_name"; | 49 private static final String PACKAGE_NAME_KEY = "last_shared_package_name"; |
40 private static final String CLASS_NAME_KEY = "last_shared_class_name"; | 50 private static final String CLASS_NAME_KEY = "last_shared_class_name"; |
41 | 51 |
42 /** | 52 /** |
43 * Intent extra for sharing screenshots via the Share intent. | 53 * Directory name for screenshots. |
44 * | |
45 * Copied from {@link android.provider.Browser} as it is marked as {@literal
@hide}. | |
46 */ | 54 */ |
47 private static final String EXTRA_SHARE_SCREENSHOT = "share_screenshot"; | 55 private static final String SCREENSHOT_DIRECTORY_NAME = "screenshot"; |
48 | 56 |
49 private ShareHelper() {} | 57 private ShareHelper() {} |
50 | 58 |
| 59 private static void deleteScreenshotFiles(File file) { |
| 60 if (!file.exists()) return; |
| 61 if (file.isDirectory()) { |
| 62 for (File f : file.listFiles()) deleteScreenshotFiles(f); |
| 63 } |
| 64 if (!file.delete()) { |
| 65 Log.w(TAG, "Failed to delete screenshot file: " + file.getAbsolutePa
th()); |
| 66 } |
| 67 } |
| 68 |
| 69 /** |
| 70 * Clears all shared screenshot files. |
| 71 */ |
| 72 public static void clearSharedScreenshots(final Context context) { |
| 73 new AsyncTask<Void, Void, Void>() { |
| 74 @Override |
| 75 protected Void doInBackground(Void... params) { |
| 76 try { |
| 77 File imagePath = UiUtils.getDirectoryForImageCapture(context
); |
| 78 deleteScreenshotFiles(new File(imagePath, SCREENSHOT_DIRECTO
RY_NAME)); |
| 79 } catch (IOException ie) { |
| 80 // Ignore exception. |
| 81 } |
| 82 return null; |
| 83 } |
| 84 }.execute(); |
| 85 } |
| 86 |
51 /** | 87 /** |
52 * Creates and shows a share intent picker dialog or starts a share intent d
irectly with the | 88 * Creates and shows a share intent picker dialog or starts a share intent d
irectly with the |
53 * activity that was most recently used to share based on shareDirectly valu
e. | 89 * activity that was most recently used to share based on shareDirectly valu
e. |
54 * | 90 * |
| 91 * This function will save |screenshot| under {app's root}/files/images/scre
enshot (or |
| 92 * /sdcard/DCIM/browser-images/screenshot if ADK is lower than JB MR2). |
| 93 * Cleaning up doesn't happen automatically, and so an app should call clear
SharedScreenshots() |
| 94 * explicitly when needed. |
| 95 * |
55 * @param shareDirectly Whether it should share directly with the activity t
hat was most | 96 * @param shareDirectly Whether it should share directly with the activity t
hat was most |
56 * recently used to share. | 97 * recently used to share. |
57 * @param activity Activity that is used to access package manager. | 98 * @param activity Activity that is used to access package manager. |
58 * @param title Title of the page to be shared. | 99 * @param title Title of the page to be shared. |
59 * @param url URL of the page to be shared. | 100 * @param url URL of the page to be shared. |
60 * @param screenshot Screenshot of the page to be shared. | 101 * @param screenshot Screenshot of the page to be shared. |
61 */ | 102 */ |
62 public static void share(boolean shareDirectly, Activity activity, String ti
tle, String url, | 103 public static void share(boolean shareDirectly, Activity activity, String ti
tle, String url, |
63 Bitmap screenshot) { | 104 Bitmap screenshot) { |
64 if (shareDirectly) { | 105 if (shareDirectly) { |
65 shareWithLastUsed(activity, title, url, screenshot); | 106 shareWithLastUsed(activity, title, url, screenshot); |
66 } else { | 107 } else { |
67 showShareDialog(activity, title, url, screenshot); | 108 showShareDialog(activity, title, url, screenshot); |
68 } | 109 } |
69 } | 110 } |
70 | 111 |
71 /** | 112 /** |
72 * Creates and shows a share intent picker dialog. | 113 * Creates and shows a share intent picker dialog. |
73 * | 114 * |
74 * @param activity Activity that is used to access package manager. | 115 * @param activity Activity that is used to access package manager. |
75 * @param title Title of the page to be shared. | 116 * @param title Title of the page to be shared. |
76 * @param url URL of the page to be shared. | 117 * @param url URL of the page to be shared. |
77 * @param screenshot Screenshot of the page to be shared. | 118 * @param screenshot Screenshot of the page to be shared. |
78 */ | 119 */ |
79 private static void showShareDialog(final Activity activity, final String ti
tle, | 120 private static void showShareDialog(final Activity activity, final String ti
tle, |
80 final String url, final Bitmap screenshot) { | 121 final String url, final Bitmap screenshot) { |
81 Intent intent = getShareIntent(title, url, screenshot); | 122 Intent intent = getShareIntent(activity, title, url, null); |
82 PackageManager manager = activity.getPackageManager(); | 123 PackageManager manager = activity.getPackageManager(); |
83 List<ResolveInfo> resolveInfoList = manager.queryIntentActivities(intent
, 0); | 124 List<ResolveInfo> resolveInfoList = manager.queryIntentActivities(intent
, 0); |
84 assert resolveInfoList.size() > 0; | 125 assert resolveInfoList.size() > 0; |
85 if (resolveInfoList.size() == 0) return; | 126 if (resolveInfoList.size() == 0) return; |
86 Collections.sort(resolveInfoList, new ResolveInfo.DisplayNameComparator(
manager)); | 127 Collections.sort(resolveInfoList, new ResolveInfo.DisplayNameComparator(
manager)); |
87 | 128 |
88 final ShareDialogAdapter adapter = | 129 final ShareDialogAdapter adapter = |
89 new ShareDialogAdapter(activity, manager, resolveInfoList); | 130 new ShareDialogAdapter(activity, manager, resolveInfoList); |
90 AlertDialog.Builder builder = new AlertDialog.Builder(activity); | 131 AlertDialog.Builder builder = new AlertDialog.Builder(activity); |
91 builder.setTitle(activity.getString(R.string.share_link_chooser_title)); | 132 builder.setTitle(activity.getString(R.string.share_link_chooser_title)); |
92 builder.setAdapter(adapter, null); | 133 builder.setAdapter(adapter, null); |
93 | 134 |
94 final AlertDialog dialog = builder.create(); | 135 final AlertDialog dialog = builder.create(); |
95 dialog.show(); | 136 dialog.show(); |
96 dialog.getListView().setOnItemClickListener(new OnItemClickListener() { | 137 dialog.getListView().setOnItemClickListener(new OnItemClickListener() { |
97 @Override | 138 @Override |
98 public void onItemClick(AdapterView<?> parent, View view, int positi
on, long id) { | 139 public void onItemClick(AdapterView<?> parent, View view, int positi
on, long id) { |
99 ResolveInfo info = adapter.getItem(position); | 140 ResolveInfo info = adapter.getItem(position); |
100 ActivityInfo ai = info.activityInfo; | 141 ActivityInfo ai = info.activityInfo; |
101 ComponentName component = | 142 ComponentName component = |
102 new ComponentName(ai.applicationInfo.packageName, ai.nam
e); | 143 new ComponentName(ai.applicationInfo.packageName, ai.nam
e); |
103 setLastShareComponentName(activity, component); | 144 setLastShareComponentName(activity, component); |
104 Intent intent = getDirectShareIntentForComponent(title, url, scr
eenshot, component); | 145 makeIntentAndShare(activity, title, url, screenshot, component); |
105 activity.startActivity(intent); | |
106 dialog.dismiss(); | 146 dialog.dismiss(); |
107 } | 147 } |
108 }); | 148 }); |
109 } | 149 } |
110 | 150 |
111 /** | 151 /** |
112 * Starts a share intent with the activity that was most recently used to sh
are. | 152 * Starts a share intent with the activity that was most recently used to sh
are. |
113 * If there is no most recently used activity, it does nothing. | 153 * If there is no most recently used activity, it does nothing. |
114 * @param activity Activity that is used to start the share intent. | 154 * @param activity Activity that is used to start the share intent. |
115 * @param title Title of the page to be shared. | 155 * @param title Title of the page to be shared. |
116 * @param url URL of the page to be shared. | 156 * @param url URL of the page to be shared. |
117 * @param screenshot Screenshot of the page to be shared. | 157 * @param screenshot Screenshot of the page to be shared. |
118 */ | 158 */ |
119 private static void shareWithLastUsed( | 159 private static void shareWithLastUsed( |
120 Activity activity, String title, String url, Bitmap screenshot) { | 160 Activity activity, String title, String url, Bitmap screenshot) { |
121 ComponentName component = getLastShareComponentName(activity); | 161 ComponentName component = getLastShareComponentName(activity); |
122 if (component == null) return; | 162 if (component == null) return; |
123 Intent intent = getDirectShareIntentForComponent(title, url, screenshot,
component); | 163 makeIntentAndShare(activity, title, url, screenshot, component); |
124 activity.startActivity(intent); | 164 } |
| 165 |
| 166 private static void makeIntentAndShare(final Activity activity, final String
title, |
| 167 final String url, final Bitmap screenshot, final ComponentName compo
nent) { |
| 168 if (screenshot == null) { |
| 169 activity.startActivity( |
| 170 getDirectShareIntentForComponent(activity, title, url, null,
component)); |
| 171 } else { |
| 172 new AsyncTask<Void, Void, Intent>() { |
| 173 @Override |
| 174 protected Intent doInBackground(Void... params) { |
| 175 return getDirectShareIntentForComponent( |
| 176 activity, title, url, screenshot, component); |
| 177 } |
| 178 |
| 179 @Override |
| 180 protected void onPostExecute(Intent intent) { |
| 181 if (ApplicationStatus.getStateForApplication() |
| 182 != ApplicationState.HAS_DESTROYED_ACTIVITIES) { |
| 183 activity.startActivity(intent); |
| 184 } |
| 185 } |
| 186 }.execute(); |
| 187 } |
125 } | 188 } |
126 | 189 |
127 /** | 190 /** |
128 * Set the icon and the title for the menu item used for direct share. | 191 * Set the icon and the title for the menu item used for direct share. |
129 * | 192 * |
130 * @param activity Activity that is used to access the package manager. | 193 * @param activity Activity that is used to access the package manager. |
131 * @param item The menu item that is used for direct share | 194 * @param item The menu item that is used for direct share |
132 */ | 195 */ |
133 public static void configureDirectShareMenuItem(Activity activity, MenuItem
item) { | 196 public static void configureDirectShareMenuItem(Activity activity, MenuItem
item) { |
134 Drawable directShareIcon = null; | 197 Drawable directShareIcon = null; |
(...skipping 12 matching lines...) Expand all Loading... |
147 } | 210 } |
148 | 211 |
149 item.setIcon(directShareIcon); | 212 item.setIcon(directShareIcon); |
150 if (directShareTitle != null) { | 213 if (directShareTitle != null) { |
151 item.setTitle(activity.getString(R.string.accessibility_menu_share_v
ia, | 214 item.setTitle(activity.getString(R.string.accessibility_menu_share_v
ia, |
152 directShareTitle)); | 215 directShareTitle)); |
153 } | 216 } |
154 } | 217 } |
155 | 218 |
156 @VisibleForTesting | 219 @VisibleForTesting |
157 public static Intent getShareIntent(String title, String url, Bitmap screens
hot) { | 220 public static Intent getShareIntent( |
| 221 Context context, String title, String url, Bitmap screenshot) { |
158 url = DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(url); | 222 url = DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(url); |
159 Intent intent = new Intent(Intent.ACTION_SEND); | 223 Intent intent = new Intent(Intent.ACTION_SEND); |
160 intent.addFlags(ApiCompatibilityUtils.getActivityNewDocumentFlag()); | 224 intent.addFlags(ApiCompatibilityUtils.getActivityNewDocumentFlag()); |
161 intent.setType("text/plain"); | 225 intent.setType("text/plain"); |
162 intent.putExtra(Intent.EXTRA_SUBJECT, title); | 226 intent.putExtra(Intent.EXTRA_SUBJECT, title); |
163 intent.putExtra(Intent.EXTRA_TEXT, url); | 227 intent.putExtra(Intent.EXTRA_TEXT, url); |
164 if (screenshot != null) intent.putExtra(EXTRA_SHARE_SCREENSHOT, screensh
ot); | 228 if (screenshot != null) { |
| 229 FileOutputStream fOut = null; |
| 230 try { |
| 231 File path = new File( |
| 232 UiUtils.getDirectoryForImageCapture(context), SCREENSHOT
_DIRECTORY_NAME); |
| 233 if (path.exists() || path.mkdir()) { |
| 234 File saveFile = File.createTempFile( |
| 235 String.valueOf(System.currentTimeMillis()), ".jpg",
path); |
| 236 fOut = new FileOutputStream(saveFile); |
| 237 screenshot.compress(Bitmap.CompressFormat.JPEG, 85, fOut); |
| 238 fOut.flush(); |
| 239 fOut.close(); |
| 240 |
| 241 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); |
| 242 intent.putExtra(Intent.EXTRA_STREAM, |
| 243 UiUtils.getUriForImageCaptureFile(context, saveFile)
); |
| 244 } |
| 245 } catch (IOException ie) { |
| 246 if (fOut != null) { |
| 247 try { |
| 248 fOut.close(); |
| 249 } catch (IOException e) { |
| 250 // Ignore exception. |
| 251 } |
| 252 } |
| 253 } |
| 254 } |
165 return intent; | 255 return intent; |
166 } | 256 } |
167 | 257 |
168 private static Intent getDirectShareIntentForComponent(String title, String
url, | 258 private static Intent getDirectShareIntentForComponent( |
169 Bitmap screenshot, ComponentName component) { | 259 Context context, String title, String url, Bitmap screenshot, Compon
entName component) { |
170 Intent intent = getShareIntent(title, url, screenshot); | 260 Intent intent = getShareIntent(context, title, url, screenshot); |
171 intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT | 261 intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT |
172 | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP); | 262 | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP); |
173 intent.setComponent(component); | 263 intent.setComponent(component); |
174 return intent; | 264 return intent; |
175 } | 265 } |
176 | 266 |
177 private static ComponentName getLastShareComponentName(Context context) { | 267 private static ComponentName getLastShareComponentName(Context context) { |
178 SharedPreferences preferences = PreferenceManager.getDefaultSharedPrefer
ences(context); | 268 SharedPreferences preferences = PreferenceManager.getDefaultSharedPrefer
ences(context); |
179 String packageName = preferences.getString(PACKAGE_NAME_KEY, null); | 269 String packageName = preferences.getString(PACKAGE_NAME_KEY, null); |
180 String className = preferences.getString(CLASS_NAME_KEY, null); | 270 String className = preferences.getString(CLASS_NAME_KEY, null); |
181 if (packageName == null || className == null) return null; | 271 if (packageName == null || className == null) return null; |
182 return new ComponentName(packageName, className); | 272 return new ComponentName(packageName, className); |
183 } | 273 } |
184 | 274 |
185 private static void setLastShareComponentName(Context context, ComponentName
component) { | 275 private static void setLastShareComponentName(Context context, ComponentName
component) { |
186 SharedPreferences preferences = PreferenceManager.getDefaultSharedPrefer
ences(context); | 276 SharedPreferences preferences = PreferenceManager.getDefaultSharedPrefer
ences(context); |
187 SharedPreferences.Editor editor = preferences.edit(); | 277 SharedPreferences.Editor editor = preferences.edit(); |
188 editor.putString(PACKAGE_NAME_KEY, component.getPackageName()); | 278 editor.putString(PACKAGE_NAME_KEY, component.getPackageName()); |
189 editor.putString(CLASS_NAME_KEY, component.getClassName()); | 279 editor.putString(CLASS_NAME_KEY, component.getClassName()); |
190 editor.apply(); | 280 editor.apply(); |
191 } | 281 } |
192 } | 282 } |
OLD | NEW |