Chromium Code Reviews| 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.annotation.TargetApi; | 7 import android.annotation.TargetApi; |
| 8 import android.app.Activity; | 8 import android.app.Activity; |
| 9 import android.app.PendingIntent; | 9 import android.app.PendingIntent; |
| 10 import android.content.BroadcastReceiver; | 10 import android.content.BroadcastReceiver; |
| 11 import android.content.ClipData; | 11 import android.content.ClipData; |
| 12 import android.content.ComponentName; | 12 import android.content.ComponentName; |
| 13 import android.content.Context; | 13 import android.content.Context; |
| 14 import android.content.Intent; | 14 import android.content.Intent; |
| 15 import android.content.IntentFilter; | 15 import android.content.IntentFilter; |
| 16 import android.content.SharedPreferences; | 16 import android.content.SharedPreferences; |
| 17 import android.content.pm.ActivityInfo; | 17 import android.content.pm.ActivityInfo; |
| 18 import android.content.pm.ApplicationInfo; | 18 import android.content.pm.ApplicationInfo; |
| 19 import android.content.pm.PackageManager; | 19 import android.content.pm.PackageManager; |
| 20 import android.content.pm.PackageManager.NameNotFoundException; | 20 import android.content.pm.PackageManager.NameNotFoundException; |
| 21 import android.content.pm.ResolveInfo; | 21 import android.content.pm.ResolveInfo; |
| 22 import android.graphics.Bitmap; | 22 import android.graphics.Bitmap; |
| 23 import android.graphics.drawable.Drawable; | 23 import android.graphics.drawable.Drawable; |
| 24 import android.net.Uri; | 24 import android.net.Uri; |
| 25 import android.os.AsyncTask; | 25 import android.os.AsyncTask; |
| 26 import android.os.Build; | 26 import android.os.Build; |
| 27 import android.support.annotation.Nullable; | |
| 27 import android.support.v7.app.AlertDialog; | 28 import android.support.v7.app.AlertDialog; |
| 28 import android.util.Pair; | 29 import android.util.Pair; |
| 29 import android.view.MenuItem; | 30 import android.view.MenuItem; |
| 30 import android.view.View; | 31 import android.view.View; |
| 31 import android.widget.AdapterView; | 32 import android.widget.AdapterView; |
| 32 import android.widget.AdapterView.OnItemClickListener; | 33 import android.widget.AdapterView.OnItemClickListener; |
| 33 | 34 |
| 34 import org.chromium.base.ApiCompatibilityUtils; | 35 import org.chromium.base.ApiCompatibilityUtils; |
| 35 import org.chromium.base.ApplicationState; | 36 import org.chromium.base.ApplicationState; |
| 36 import org.chromium.base.ApplicationStatus; | 37 import org.chromium.base.ApplicationStatus; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 82 if (!file.exists()) return; | 83 if (!file.exists()) return; |
| 83 if (file.isDirectory()) { | 84 if (file.isDirectory()) { |
| 84 for (File f : file.listFiles()) deleteShareImageFiles(f); | 85 for (File f : file.listFiles()) deleteShareImageFiles(f); |
| 85 } | 86 } |
| 86 if (!file.delete()) { | 87 if (!file.delete()) { |
| 87 Log.w(TAG, "Failed to delete share image file: %s", file.getAbsolute Path()); | 88 Log.w(TAG, "Failed to delete share image file: %s", file.getAbsolute Path()); |
| 88 } | 89 } |
| 89 } | 90 } |
| 90 | 91 |
| 91 /** | 92 /** |
| 93 * Callback interface for when a target is chosen. | |
| 94 */ | |
| 95 public static interface TargetChosenCallback { | |
| 96 /** | |
| 97 * Called when the user chooses a target in the share dialog. | |
| 98 * | |
| 99 * Note that if the user cancels the share dialog, this callback is neve r called. | |
| 100 */ | |
| 101 public void onTargetChosen(ComponentName chosenComponent); | |
| 102 } | |
| 103 | |
| 104 /** | |
| 92 * Receiver to record the chosen component when sharing an Intent. | 105 * Receiver to record the chosen component when sharing an Intent. |
| 93 */ | 106 */ |
| 94 static class TargetChosenReceiver extends BroadcastReceiver { | 107 static class TargetChosenReceiver extends BroadcastReceiver { |
| 95 private static final String EXTRA_RECEIVER_TOKEN = "receiver_token"; | 108 private static final String EXTRA_RECEIVER_TOKEN = "receiver_token"; |
| 96 private static final Object LOCK = new Object(); | 109 private static final Object LOCK = new Object(); |
| 97 | 110 |
| 98 private static String sTargetChosenReceiveAction; | 111 private static String sTargetChosenReceiveAction; |
| 99 private static TargetChosenReceiver sLastRegisteredReceiver; | 112 private static TargetChosenReceiver sLastRegisteredReceiver; |
| 100 | 113 |
| 114 private final boolean mSaveLastUsed; | |
| 115 @Nullable private final TargetChosenCallback mCallback; | |
| 116 | |
| 117 private TargetChosenReceiver(boolean saveLastUsed, | |
| 118 @Nullable TargetChosenCallback callback) { | |
| 119 mSaveLastUsed = saveLastUsed; | |
| 120 mCallback = callback; | |
| 121 } | |
| 122 | |
| 101 static boolean isSupported() { | 123 static boolean isSupported() { |
| 102 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1; | 124 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1; |
| 103 } | 125 } |
| 104 | 126 |
| 105 @TargetApi(Build.VERSION_CODES.LOLLIPOP_MR1) | 127 @TargetApi(Build.VERSION_CODES.LOLLIPOP_MR1) |
| 106 static void sendChooserIntent(Activity activity, Intent sharingIntent) { | 128 static void sendChooserIntent(boolean saveLastUsed, Activity activity, |
| 129 Intent sharingIntent, | |
| 130 @Nullable TargetChosenCallback callback) { | |
| 107 synchronized (LOCK) { | 131 synchronized (LOCK) { |
| 108 if (sTargetChosenReceiveAction == null) { | 132 if (sTargetChosenReceiveAction == null) { |
| 109 sTargetChosenReceiveAction = activity.getPackageName() + "/" | 133 sTargetChosenReceiveAction = activity.getPackageName() + "/" |
| 110 + TargetChosenReceiver.class.getName() + "_ACTION"; | 134 + TargetChosenReceiver.class.getName() + "_ACTION"; |
| 111 } | 135 } |
| 112 Context context = activity.getApplicationContext(); | 136 Context context = activity.getApplicationContext(); |
| 113 if (sLastRegisteredReceiver != null) { | 137 if (sLastRegisteredReceiver != null) { |
| 114 context.unregisterReceiver(sLastRegisteredReceiver); | 138 context.unregisterReceiver(sLastRegisteredReceiver); |
| 115 } | 139 } |
| 116 sLastRegisteredReceiver = new TargetChosenReceiver(); | 140 sLastRegisteredReceiver = new TargetChosenReceiver(saveLastUsed, callback); |
| 117 context.registerReceiver( | 141 context.registerReceiver( |
| 118 sLastRegisteredReceiver, new IntentFilter(sTargetChosenR eceiveAction)); | 142 sLastRegisteredReceiver, new IntentFilter(sTargetChosenR eceiveAction)); |
| 119 } | 143 } |
| 120 | 144 |
| 121 Intent intent = new Intent(sTargetChosenReceiveAction); | 145 Intent intent = new Intent(sTargetChosenReceiveAction); |
| 122 intent.setPackage(activity.getPackageName()); | 146 intent.setPackage(activity.getPackageName()); |
| 123 intent.putExtra(EXTRA_RECEIVER_TOKEN, sLastRegisteredReceiver.hashCo de()); | 147 intent.putExtra(EXTRA_RECEIVER_TOKEN, sLastRegisteredReceiver.hashCo de()); |
| 124 final PendingIntent callback = PendingIntent.getBroadcast(activity, 0, intent, | 148 final PendingIntent pendingIntent = PendingIntent.getBroadcast(activ ity, 0, intent, |
| 125 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_S HOT); | 149 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_S HOT); |
| 126 Intent chooserIntent = Intent.createChooser(sharingIntent, | 150 Intent chooserIntent = Intent.createChooser(sharingIntent, |
| 127 activity.getString(R.string.share_link_chooser_title), | 151 activity.getString(R.string.share_link_chooser_title), |
| 128 callback.getIntentSender()); | 152 pendingIntent.getIntentSender()); |
| 129 activity.startActivity(chooserIntent); | 153 activity.startActivity(chooserIntent); |
| 130 } | 154 } |
| 131 | 155 |
| 132 @Override | 156 @Override |
| 133 public void onReceive(Context context, Intent intent) { | 157 public void onReceive(Context context, Intent intent) { |
| 134 synchronized (LOCK) { | 158 synchronized (LOCK) { |
| 135 if (sLastRegisteredReceiver != this) return; | 159 if (sLastRegisteredReceiver != this) return; |
| 136 context.getApplicationContext().unregisterReceiver(sLastRegister edReceiver); | 160 context.getApplicationContext().unregisterReceiver(sLastRegister edReceiver); |
| 137 sLastRegisteredReceiver = null; | 161 sLastRegisteredReceiver = null; |
| 138 } | 162 } |
| 139 if (!intent.hasExtra(EXTRA_RECEIVER_TOKEN) | 163 if (!intent.hasExtra(EXTRA_RECEIVER_TOKEN) |
| 140 || intent.getIntExtra(EXTRA_RECEIVER_TOKEN, 0) != this.hashC ode()) { | 164 || intent.getIntExtra(EXTRA_RECEIVER_TOKEN, 0) != this.hashC ode()) { |
| 141 return; | 165 return; |
| 142 } | 166 } |
| 143 | 167 |
| 144 ComponentName target = intent.getParcelableExtra(Intent.EXTRA_CHOSEN _COMPONENT); | 168 ComponentName target = intent.getParcelableExtra(Intent.EXTRA_CHOSEN _COMPONENT); |
| 145 if (target != null) { | 169 if (mCallback != null) { |
| 170 mCallback.onTargetChosen(target); | |
| 171 } | |
| 172 if (mSaveLastUsed && target != null) { | |
| 146 setLastShareComponentName(target); | 173 setLastShareComponentName(target); |
| 147 } | 174 } |
| 148 } | 175 } |
| 149 } | 176 } |
| 150 | 177 |
| 151 /** | 178 /** |
| 152 * Clears all shared image files. | 179 * Clears all shared image files. |
| 153 */ | 180 */ |
| 154 public static void clearSharedImages(final Context context) { | 181 public static void clearSharedImages(final Context context) { |
| 155 new AsyncTask<Void, Void, Void>() { | 182 new AsyncTask<Void, Void, Void>() { |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 170 * Creates and shows a share intent picker dialog or starts a share intent d irectly with the | 197 * Creates and shows a share intent picker dialog or starts a share intent d irectly with the |
| 171 * activity that was most recently used to share based on shareDirectly valu e. | 198 * activity that was most recently used to share based on shareDirectly valu e. |
| 172 * | 199 * |
| 173 * This function will save |screenshot| under {app's root}/files/images/scre enshot (or | 200 * This function will save |screenshot| under {app's root}/files/images/scre enshot (or |
| 174 * /sdcard/DCIM/browser-images/screenshot if ADK is lower than JB MR2). | 201 * /sdcard/DCIM/browser-images/screenshot if ADK is lower than JB MR2). |
| 175 * Cleaning up doesn't happen automatically, and so an app should call clear SharedScreenshots() | 202 * Cleaning up doesn't happen automatically, and so an app should call clear SharedScreenshots() |
| 176 * explicitly when needed. | 203 * explicitly when needed. |
| 177 * | 204 * |
| 178 * @param shareDirectly Whether it should share directly with the activity t hat was most | 205 * @param shareDirectly Whether it should share directly with the activity t hat was most |
| 179 * recently used to share. | 206 * recently used to share. |
| 207 * @param saveLastUsed Whether to save the chosen activity for future direct sharing. | |
| 180 * @param activity Activity that is used to access package manager. | 208 * @param activity Activity that is used to access package manager. |
| 181 * @param title Title of the page to be shared. | 209 * @param title Title of the page to be shared. |
| 210 * @param text Text to be shared. If both |text| and |url| are supplied, the y are concatenated | |
| 211 * with a space. | |
| 182 * @param url URL of the page to be shared. | 212 * @param url URL of the page to be shared. |
| 183 * @param screenshot Screenshot of the page to be shared. | 213 * @param screenshot Screenshot of the page to be shared. |
| 214 * @param callback Optional callback to be called when user makes a choice. Will not be called | |
| 215 * if receiving a response when the user makes a choice is n ot supported (on | |
| 216 * older Android versions). | |
| 184 */ | 217 */ |
| 185 public static void share(boolean shareDirectly, Activity activity, String ti tle, String url, | 218 public static void share(boolean shareDirectly, boolean saveLastUsed, Activi ty activity, |
| 186 Bitmap screenshot) { | 219 String title, String text, String url, Bitmap screenshot, |
| 220 @Nullable TargetChosenCallback callback) { | |
| 187 if (shareDirectly) { | 221 if (shareDirectly) { |
| 188 shareWithLastUsed(activity, title, url, screenshot); | 222 shareWithLastUsed(activity, title, text, url, screenshot); |
| 189 } else if (TargetChosenReceiver.isSupported()) { | 223 } else if (TargetChosenReceiver.isSupported()) { |
| 190 makeIntentAndShare(activity, title, url, screenshot, null); | 224 makeIntentAndShare(saveLastUsed, activity, title, text, url, screens hot, null, |
| 225 callback); | |
| 191 } else { | 226 } else { |
| 192 showShareDialog(activity, title, url, screenshot); | 227 showShareDialog(saveLastUsed, activity, title, text, url, screenshot , callback); |
| 193 } | 228 } |
| 194 } | 229 } |
| 195 | 230 |
| 196 /** | 231 /** |
| 197 * Trigger the share action for the given image data. | 232 * Trigger the share action for the given image data. |
| 198 * @param activity The activity used to trigger the share action. | 233 * @param activity The activity used to trigger the share action. |
| 199 * @param jpegImageData The image data to be shared in jpeg format. | 234 * @param jpegImageData The image data to be shared in jpeg format. |
| 200 */ | 235 */ |
| 201 public static void shareImage(final Activity activity, final byte[] jpegImag eData) { | 236 public static void shareImage(final Activity activity, final byte[] jpegImag eData) { |
| 202 if (jpegImageData.length == 0) { | 237 if (jpegImageData.length == 0) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 248 activity.getString(R.string.share_link_chooser_title )); | 283 activity.getString(R.string.share_link_chooser_title )); |
| 249 activity.startActivity(chooserIntent); | 284 activity.startActivity(chooserIntent); |
| 250 } | 285 } |
| 251 } | 286 } |
| 252 }.execute(); | 287 }.execute(); |
| 253 } | 288 } |
| 254 | 289 |
| 255 /** | 290 /** |
| 256 * Creates and shows a share intent picker dialog. | 291 * Creates and shows a share intent picker dialog. |
| 257 * | 292 * |
| 293 * @param saveLastUsed Whether to save the chosen activity for future direct sharing. | |
| 258 * @param activity Activity that is used to access package manager. | 294 * @param activity Activity that is used to access package manager. |
| 259 * @param title Title of the page to be shared. | 295 * @param title Title of the page to be shared. |
| 296 * @param text Text to be shared. If both |text| and |url| are supplied, the y are concatenated | |
| 297 * with a space. | |
| 260 * @param url URL of the page to be shared. | 298 * @param url URL of the page to be shared. |
| 261 * @param screenshot Screenshot of the page to be shared. | 299 * @param screenshot Screenshot of the page to be shared. |
| 300 * @param callback Optional callback to be called when user makes a choice. Will not be called | |
| 301 * if receiving a response when the user makes a choice is n ot supported (on | |
| 302 * older Android versions). | |
| 262 */ | 303 */ |
| 263 private static void showShareDialog(final Activity activity, final String ti tle, | 304 private static void showShareDialog(final boolean saveLastUsed, final Activi ty activity, |
| 264 final String url, final Bitmap screenshot) { | 305 final String title, final String text, final String url, final Bitma p screenshot, |
| 265 Intent intent = getShareIntent(activity, title, url, null); | 306 @Nullable final TargetChosenCallback callback) { |
| 307 Intent intent = getShareIntent(activity, title, text, url, null); | |
| 266 PackageManager manager = activity.getPackageManager(); | 308 PackageManager manager = activity.getPackageManager(); |
| 267 List<ResolveInfo> resolveInfoList = manager.queryIntentActivities(intent , 0); | 309 List<ResolveInfo> resolveInfoList = manager.queryIntentActivities(intent , 0); |
| 268 assert resolveInfoList.size() > 0; | 310 assert resolveInfoList.size() > 0; |
| 269 if (resolveInfoList.size() == 0) return; | 311 if (resolveInfoList.size() == 0) return; |
| 270 Collections.sort(resolveInfoList, new ResolveInfo.DisplayNameComparator( manager)); | 312 Collections.sort(resolveInfoList, new ResolveInfo.DisplayNameComparator( manager)); |
| 271 | 313 |
| 272 final ShareDialogAdapter adapter = | 314 final ShareDialogAdapter adapter = |
| 273 new ShareDialogAdapter(activity, manager, resolveInfoList); | 315 new ShareDialogAdapter(activity, manager, resolveInfoList); |
| 274 AlertDialog.Builder builder = new AlertDialog.Builder(activity, R.style. AlertDialogTheme); | 316 AlertDialog.Builder builder = new AlertDialog.Builder(activity, R.style. AlertDialogTheme); |
| 275 builder.setTitle(activity.getString(R.string.share_link_chooser_title)); | 317 builder.setTitle(activity.getString(R.string.share_link_chooser_title)); |
| 276 builder.setAdapter(adapter, null); | 318 builder.setAdapter(adapter, null); |
| 277 | 319 |
| 278 final AlertDialog dialog = builder.create(); | 320 final AlertDialog dialog = builder.create(); |
| 279 dialog.show(); | 321 dialog.show(); |
| 280 dialog.getListView().setOnItemClickListener(new OnItemClickListener() { | 322 dialog.getListView().setOnItemClickListener(new OnItemClickListener() { |
| 281 @Override | 323 @Override |
| 282 public void onItemClick(AdapterView<?> parent, View view, int positi on, long id) { | 324 public void onItemClick(AdapterView<?> parent, View view, int positi on, long id) { |
| 283 ResolveInfo info = adapter.getItem(position); | 325 ResolveInfo info = adapter.getItem(position); |
| 284 ActivityInfo ai = info.activityInfo; | 326 ActivityInfo ai = info.activityInfo; |
| 285 ComponentName component = | 327 ComponentName component = |
| 286 new ComponentName(ai.applicationInfo.packageName, ai.nam e); | 328 new ComponentName(ai.applicationInfo.packageName, ai.nam e); |
| 287 setLastShareComponentName(component); | 329 callback.onTargetChosen(component); |
| 288 makeIntentAndShare(activity, title, url, screenshot, component); | 330 if (saveLastUsed) setLastShareComponentName(component); |
| 331 makeIntentAndShare(false, activity, title, text, url, screenshot , component, | |
| 332 null); | |
| 289 dialog.dismiss(); | 333 dialog.dismiss(); |
| 290 } | 334 } |
| 291 }); | 335 }); |
| 292 } | 336 } |
| 293 | 337 |
| 294 /** | 338 /** |
| 295 * Starts a share intent with the activity that was most recently used to sh are. | 339 * Starts a share intent with the activity that was most recently used to sh are. |
| 296 * If there is no most recently used activity, it does nothing. | 340 * If there is no most recently used activity, it does nothing. |
| 297 * @param activity Activity that is used to start the share intent. | 341 * @param activity Activity that is used to start the share intent. |
| 298 * @param title Title of the page to be shared. | 342 * @param title Title of the page to be shared. |
| 343 * @param text Text to be shared. If both |text| and |url| are supplied, the y are concatenated | |
| 344 * with a space. | |
| 299 * @param url URL of the page to be shared. | 345 * @param url URL of the page to be shared. |
| 300 * @param screenshot Screenshot of the page to be shared. | 346 * @param screenshot Screenshot of the page to be shared. |
| 301 */ | 347 */ |
| 302 private static void shareWithLastUsed( | 348 private static void shareWithLastUsed( |
| 303 Activity activity, String title, String url, Bitmap screenshot) { | 349 Activity activity, String title, String text, String url, Bitmap scr eenshot) { |
| 304 ComponentName component = getLastShareComponentName(); | 350 ComponentName component = getLastShareComponentName(); |
| 305 if (component == null) return; | 351 if (component == null) return; |
| 306 makeIntentAndShare(activity, title, url, screenshot, component); | 352 makeIntentAndShare(false, activity, title, text, url, screenshot, compon ent, null); |
| 307 } | 353 } |
| 308 | 354 |
| 309 private static void shareIntent(Activity activity, Intent sharingIntent) { | 355 private static void shareIntent(boolean saveLastUsed, Activity activity, Int ent sharingIntent, |
| 356 @Nullable TargetChosenCallback callback) { | |
| 310 if (sharingIntent.getComponent() != null) { | 357 if (sharingIntent.getComponent() != null) { |
| 358 // If a component was specified, there should not also be a callback . | |
| 359 assert callback == null; | |
| 311 activity.startActivity(sharingIntent); | 360 activity.startActivity(sharingIntent); |
| 312 } else { | 361 } else { |
| 313 assert TargetChosenReceiver.isSupported(); | 362 assert TargetChosenReceiver.isSupported(); |
| 314 TargetChosenReceiver.sendChooserIntent(activity, sharingIntent); | 363 TargetChosenReceiver.sendChooserIntent(saveLastUsed, activity, shari ngIntent, callback); |
| 315 } | 364 } |
| 316 } | 365 } |
| 317 | 366 |
| 318 private static void makeIntentAndShare(final Activity activity, final String title, | 367 private static void makeIntentAndShare(final boolean saveLastUsed, final Act ivity activity, |
| 319 final String url, final Bitmap screenshot, final ComponentName compo nent) { | 368 final String title, final String text, final String url, final Bitma p screenshot, |
| 369 final ComponentName component, @Nullable final TargetChosenCallback callback) { | |
| 320 if (screenshot == null) { | 370 if (screenshot == null) { |
| 321 shareIntent(activity, | 371 shareIntent( |
| 322 getDirectShareIntentForComponent(activity, title, url, null, component)); | 372 saveLastUsed, activity, |
| 373 getDirectShareIntentForComponent(activity, title, text, url, null, component), | |
| 374 callback); | |
| 323 } else { | 375 } else { |
| 324 new AsyncTask<Void, Void, File>() { | 376 new AsyncTask<Void, Void, File>() { |
| 325 @Override | 377 @Override |
| 326 protected File doInBackground(Void... params) { | 378 protected File doInBackground(Void... params) { |
| 327 FileOutputStream fOut = null; | 379 FileOutputStream fOut = null; |
| 328 try { | 380 try { |
| 329 File path = new File(UiUtils.getDirectoryForImageCapture (activity), | 381 File path = new File(UiUtils.getDirectoryForImageCapture (activity), |
| 330 SHARE_IMAGES_DIRECTORY_NAME); | 382 SHARE_IMAGES_DIRECTORY_NAME); |
| 331 if (path.exists() || path.mkdir()) { | 383 if (path.exists() || path.mkdir()) { |
| 332 File saveFile = File.createTempFile( | 384 File saveFile = File.createTempFile( |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 351 | 403 |
| 352 return null; | 404 return null; |
| 353 } | 405 } |
| 354 | 406 |
| 355 @Override | 407 @Override |
| 356 protected void onPostExecute(File saveFile) { | 408 protected void onPostExecute(File saveFile) { |
| 357 if (ApplicationStatus.getStateForApplication() | 409 if (ApplicationStatus.getStateForApplication() |
| 358 != ApplicationState.HAS_DESTROYED_ACTIVITIES) { | 410 != ApplicationState.HAS_DESTROYED_ACTIVITIES) { |
| 359 Uri screenshotUri = saveFile == null | 411 Uri screenshotUri = saveFile == null |
| 360 ? null : UiUtils.getUriForImageCaptureFile(activ ity, saveFile); | 412 ? null : UiUtils.getUriForImageCaptureFile(activ ity, saveFile); |
| 361 shareIntent(activity, getDirectShareIntentForComponent( | 413 shareIntent( |
| 362 activity, title, url, screenshotUri, component)) ; | 414 saveLastUsed, activity, |
| 415 getDirectShareIntentForComponent(activity, title , text, url, | |
| 416 screenshotUri, component), | |
| 417 callback); | |
| 363 } | 418 } |
| 364 } | 419 } |
| 365 }.execute(); | 420 }.execute(); |
| 366 } | 421 } |
| 367 } | 422 } |
| 368 | 423 |
| 369 /** | 424 /** |
| 370 * Set the icon and the title for the menu item used for direct share. | 425 * Set the icon and the title for the menu item used for direct share. |
| 371 * | 426 * |
| 372 * @param activity Activity that is used to access the package manager. | 427 * @param activity Activity that is used to access the package manager. |
| 373 * @param item The menu item that is used for direct share | 428 * @param item The menu item that is used for direct share |
| 374 */ | 429 */ |
| 375 public static void configureDirectShareMenuItem(Activity activity, MenuItem item) { | 430 public static void configureDirectShareMenuItem(Activity activity, MenuItem item) { |
| 376 Drawable directShareIcon = null; | 431 Drawable directShareIcon = null; |
| 377 CharSequence directShareTitle = null; | 432 CharSequence directShareTitle = null; |
| 378 | 433 |
| 379 final ComponentName component = getLastShareComponentName(); | 434 final ComponentName component = getLastShareComponentName(); |
| 380 boolean isComponentValid = false; | 435 boolean isComponentValid = false; |
| 381 if (component != null) { | 436 if (component != null) { |
| 382 Intent intent = getShareIntent(activity, "", "", null); | 437 Intent intent = getShareIntent(activity, "", "", "", null); |
| 383 intent.setPackage(component.getPackageName()); | 438 intent.setPackage(component.getPackageName()); |
| 384 PackageManager manager = activity.getPackageManager(); | 439 PackageManager manager = activity.getPackageManager(); |
| 385 List<ResolveInfo> resolveInfoList = manager.queryIntentActivities(in tent, 0); | 440 List<ResolveInfo> resolveInfoList = manager.queryIntentActivities(in tent, 0); |
| 386 for (ResolveInfo info : resolveInfoList) { | 441 for (ResolveInfo info : resolveInfoList) { |
| 387 ActivityInfo ai = info.activityInfo; | 442 ActivityInfo ai = info.activityInfo; |
| 388 if (component.equals(new ComponentName(ai.applicationInfo.packag eName, ai.name))) { | 443 if (component.equals(new ComponentName(ai.applicationInfo.packag eName, ai.name))) { |
| 389 isComponentValid = true; | 444 isComponentValid = true; |
| 390 break; | 445 break; |
| 391 } | 446 } |
| 392 } | 447 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 432 | 487 |
| 433 item.setIcon(directShareIcon); | 488 item.setIcon(directShareIcon); |
| 434 if (directShareTitle != null) { | 489 if (directShareTitle != null) { |
| 435 item.setTitle(activity.getString(R.string.accessibility_menu_share_v ia, | 490 item.setTitle(activity.getString(R.string.accessibility_menu_share_v ia, |
| 436 directShareTitle)); | 491 directShareTitle)); |
| 437 } | 492 } |
| 438 } | 493 } |
| 439 | 494 |
| 440 @VisibleForTesting | 495 @VisibleForTesting |
| 441 protected static Intent getShareIntent( | 496 protected static Intent getShareIntent( |
| 442 Activity activity, String title, String url, Uri screenshotUri) { | 497 Activity activity, String title, String text, String url, Uri screen shotUri) { |
| 443 url = DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(url); | 498 if (url != null && url.length() > 0) { |
|
David Trainor- moved to gerrit
2016/08/05 16:06:54
!TextUtils.isEmpty(url)? Same for below?
Matt Giuca
2016/08/08 04:54:43
Done.
| |
| 499 url = DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(url); | |
| 500 if (text != null && text.length() > 0) { | |
| 501 // Concatenate text and URL with a space. | |
| 502 text = text + " " + url; | |
| 503 } else { | |
| 504 text = url; | |
| 505 } | |
| 506 } | |
| 507 | |
| 444 Intent intent = new Intent(Intent.ACTION_SEND); | 508 Intent intent = new Intent(Intent.ACTION_SEND); |
| 445 intent.addFlags(ApiCompatibilityUtils.getActivityNewDocumentFlag()); | 509 intent.addFlags(ApiCompatibilityUtils.getActivityNewDocumentFlag()); |
| 446 intent.setType("text/plain"); | 510 intent.setType("text/plain"); |
| 447 intent.putExtra(Intent.EXTRA_SUBJECT, title); | 511 intent.putExtra(Intent.EXTRA_SUBJECT, title); |
| 448 intent.putExtra(Intent.EXTRA_TEXT, url); | 512 intent.putExtra(Intent.EXTRA_TEXT, text); |
| 449 intent.putExtra(EXTRA_TASK_ID, activity.getTaskId()); | 513 intent.putExtra(EXTRA_TASK_ID, activity.getTaskId()); |
| 450 | 514 |
| 451 if (screenshotUri != null) { | 515 if (screenshotUri != null) { |
| 452 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); | 516 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); |
| 453 // To give read access to an Intent target, we need to put |screensh otUri| in clipData | 517 // To give read access to an Intent target, we need to put |screensh otUri| in clipData |
| 454 // because adding Intent.FLAG_GRANT_READ_URI_PERMISSION doesn't work for | 518 // because adding Intent.FLAG_GRANT_READ_URI_PERMISSION doesn't work for |
| 455 // EXTRA_SHARE_SCREENSHOT_AS_STREAM. | 519 // EXTRA_SHARE_SCREENSHOT_AS_STREAM. |
| 456 intent.setClipData(ClipData.newRawUri("", screenshotUri)); | 520 intent.setClipData(ClipData.newRawUri("", screenshotUri)); |
| 457 intent.putExtra(EXTRA_SHARE_SCREENSHOT_AS_STREAM, screenshotUri); | 521 intent.putExtra(EXTRA_SHARE_SCREENSHOT_AS_STREAM, screenshotUri); |
| 458 } | 522 } |
| 459 return intent; | 523 return intent; |
| 460 } | 524 } |
| 461 | 525 |
| 462 private static Intent getShareImageIntent(Uri imageUri) { | 526 private static Intent getShareImageIntent(Uri imageUri) { |
| 463 Intent intent = new Intent(Intent.ACTION_SEND); | 527 Intent intent = new Intent(Intent.ACTION_SEND); |
| 464 intent.addFlags(ApiCompatibilityUtils.getActivityNewDocumentFlag()); | 528 intent.addFlags(ApiCompatibilityUtils.getActivityNewDocumentFlag()); |
| 465 intent.setType("image/jpeg"); | 529 intent.setType("image/jpeg"); |
| 466 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); | 530 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); |
| 467 intent.putExtra(Intent.EXTRA_STREAM, imageUri); | 531 intent.putExtra(Intent.EXTRA_STREAM, imageUri); |
| 468 return intent; | 532 return intent; |
| 469 } | 533 } |
| 470 | 534 |
| 471 private static Intent getDirectShareIntentForComponent( | 535 private static Intent getDirectShareIntentForComponent( |
| 472 Activity activity, String title, String url, | 536 Activity activity, String title, String text, String url, |
| 473 Uri screenshotUri, ComponentName component) { | 537 Uri screenshotUri, ComponentName component) { |
| 474 Intent intent = getShareIntent(activity, title, url, screenshotUri); | 538 Intent intent = getShareIntent(activity, title, text, url, screenshotUri ); |
| 475 intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT | 539 intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT |
| 476 | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP); | 540 | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP); |
| 477 intent.setComponent(component); | 541 intent.setComponent(component); |
| 478 return intent; | 542 return intent; |
| 479 } | 543 } |
| 480 | 544 |
| 481 private static ComponentName getLastShareComponentName() { | 545 private static ComponentName getLastShareComponentName() { |
| 482 SharedPreferences preferences = ContextUtils.getAppSharedPreferences(); | 546 SharedPreferences preferences = ContextUtils.getAppSharedPreferences(); |
| 483 String packageName = preferences.getString(PACKAGE_NAME_KEY, null); | 547 String packageName = preferences.getString(PACKAGE_NAME_KEY, null); |
| 484 String className = preferences.getString(CLASS_NAME_KEY, null); | 548 String className = preferences.getString(CLASS_NAME_KEY, null); |
| 485 if (packageName == null || className == null) return null; | 549 if (packageName == null || className == null) return null; |
| 486 return new ComponentName(packageName, className); | 550 return new ComponentName(packageName, className); |
| 487 } | 551 } |
| 488 | 552 |
| 489 private static void setLastShareComponentName(ComponentName component) { | 553 private static void setLastShareComponentName(ComponentName component) { |
| 490 SharedPreferences preferences = ContextUtils.getAppSharedPreferences(); | 554 SharedPreferences preferences = ContextUtils.getAppSharedPreferences(); |
| 491 SharedPreferences.Editor editor = preferences.edit(); | 555 SharedPreferences.Editor editor = preferences.edit(); |
| 492 editor.putString(PACKAGE_NAME_KEY, component.getPackageName()); | 556 editor.putString(PACKAGE_NAME_KEY, component.getPackageName()); |
| 493 editor.putString(CLASS_NAME_KEY, component.getClassName()); | 557 editor.putString(CLASS_NAME_KEY, component.getClassName()); |
| 494 editor.apply(); | 558 editor.apply(); |
| 495 } | 559 } |
| 496 } | 560 } |
| OLD | NEW |