ShareCompat.java revision 14ad84e85a8c09b016a621f0f0017594e0d7864b
1/* 2 * Copyright (C) 2011 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 17package android.support.v4.app; 18 19import android.app.Activity; 20import android.content.ComponentName; 21import android.content.Intent; 22import android.content.pm.PackageManager; 23import android.content.pm.PackageManager.NameNotFoundException; 24import android.graphics.drawable.Drawable; 25import android.net.Uri; 26import android.os.Build; 27import android.support.v4.view.MenuItemCompat; 28import android.util.Log; 29import android.view.Menu; 30import android.view.MenuItem; 31 32import java.util.ArrayList; 33 34/** 35 * Extra helper functionality for sharing data between activities. 36 * 37 * ShareCompat provides functionality to extend the {@link Intent#ACTION_SEND}/ 38 * {@link Intent#ACTION_SEND_MULTIPLE} protocol and support retrieving more info 39 * about the activity that invoked a social sharing action. 40 * 41 * {@link IntentBuilder} provides helper functions for constructing a sharing 42 * intent that always includes data about the calling activity and app. 43 * This lets the called activity provide attribution for the app that shared 44 * content. Constructing an intent this way can be done in a method-chaining style. 45 * To obtain an IntentBuilder with info about your calling activity, use the static 46 * method {@link IntentBuilder#from(Activity)}. 47 * 48 * {@link IntentReader} provides helper functions for parsing the defined extras 49 * within an {@link Intent#ACTION_SEND} or {@link Intent#ACTION_SEND_MULTIPLE} intent 50 * used to launch an activity. You can also obtain a Drawable for the caller's 51 * application icon and the application's localized label (the app's human-readable name). 52 * Social apps that enable sharing content are encouraged to use this information 53 * to call out the app that the content was shared from. 54 */ 55public class ShareCompat { 56 /** 57 * Intent extra that stores the name of the calling package for an ACTION_SEND intent. 58 * When an activity is started using startActivityForResult this is redundant info. 59 * (It is also provided by {@link Activity#getCallingPackage()}.) 60 * 61 * Instead of using this constant directly, consider using {@link #getCallingPackage(Activity)} 62 * or {@link IntentReader#getCallingPackage()}. 63 */ 64 public static final String EXTRA_CALLING_PACKAGE = 65 "android.support.v4.app.EXTRA_CALLING_PACKAGE"; 66 67 /** 68 * Intent extra that stores the {@link ComponentName} of the calling activity for 69 * an ACTION_SEND intent. 70 */ 71 public static final String EXTRA_CALLING_ACTIVITY = 72 "android.support.v4.app.EXTRA_CALLING_ACTIVITY"; 73 74 /** 75 * Request code used by {@link IntentBuilder#startChooserForResult()} when it calls 76 * {@link Activity#startActivityForResult(Intent, int)}. If you wish to respond 77 * to the result code for a share action, look for a call to onActivityResult 78 * with this request code. 79 */ 80 public static final int REQUEST_CODE = ('S' << 16) | ('H' << 8) | 'A'; 81 82 /** 83 * Compatibility shims for sharing operations 84 */ 85 interface ShareCompatImpl { 86 void configureMenuItem(MenuItem item, IntentBuilder shareIntent); 87 } 88 89 static class ShareCompatImplBase implements ShareCompatImpl { 90 public void configureMenuItem(MenuItem item, IntentBuilder shareIntent) { 91 item.setIntent(shareIntent.createChooserIntent()); 92 } 93 } 94 95 static class ShareCompatImplICS implements ShareCompatImpl { 96 public void configureMenuItem(MenuItem item, IntentBuilder shareIntent) { 97 ShareCompatICS.configureMenuItem(item, shareIntent.getActivity(), 98 shareIntent.getIntent()); 99 } 100 } 101 102 private static ShareCompatImpl IMPL; 103 104 static { 105 if (Build.VERSION.SDK_INT >= 14) { 106 IMPL = new ShareCompatImplICS(); 107 } else { 108 IMPL = new ShareCompatImplBase(); 109 } 110 } 111 112 /** 113 * Retrieve the name of the package that launched calledActivity from a share intent. 114 * Apps that provide social sharing functionality can use this to provide attribution 115 * for the app that shared the content. 116 * 117 * <p><em>Note:</em> This data may have been provided voluntarily by the calling 118 * application. As such it should not be trusted for accuracy in the context of 119 * security or verification.</p> 120 * 121 * @param calledActivity Current activity that was launched to share content 122 * @return Name of the calling package 123 */ 124 public static String getCallingPackage(Activity calledActivity) { 125 String result = calledActivity.getCallingPackage(); 126 if (result == null) { 127 result = calledActivity.getIntent().getStringExtra(EXTRA_CALLING_PACKAGE); 128 } 129 return result; 130 } 131 132 /** 133 * Retrieve the ComponentName of the activity that launched calledActivity from a share intent. 134 * Apps that provide social sharing functionality can use this to provide attribution 135 * for the app that shared the content. 136 * 137 * <p><em>Note:</em> This data may have been provided voluntarily by the calling 138 * application. As such it should not be trusted for accuracy in the context of 139 * security or verification.</p> 140 * 141 * @param calledActivity Current activity that was launched to share content 142 * @return ComponentName of the calling activity 143 */ 144 public static ComponentName getCallingActivity(Activity calledActivity) { 145 ComponentName result = calledActivity.getCallingActivity(); 146 if (result == null) { 147 result = calledActivity.getIntent().getParcelableExtra(EXTRA_CALLING_ACTIVITY); 148 } 149 return result; 150 } 151 152 /** 153 * Configure a {@link MenuItem} to act as a sharing action. 154 * 155 * <p>If the app is running on API level 14 or higher (Android 4.0/Ice Cream Sandwich) 156 * this method will configure a ShareActionProvider to provide a more robust UI 157 * for selecting the target of the share. History will be tracked for each calling 158 * activity in a file named with the prefix ".sharecompat_" in the application's 159 * private data directory. If the application wishes to set this MenuItem to show 160 * as an action in the Action Bar it should use 161 * {@link MenuItemCompat#setShowAsAction(MenuItem, int)} to request that behavior 162 * in addition to calling this method.</p> 163 * 164 * <p>If the app is running on an older platform version this method will configure 165 * a standard activity chooser dialog for the menu item.</p> 166 * 167 * <p>During the calling activity's lifecycle, if data within the share intent must 168 * change the app should change that state in one of several ways:</p> 169 * <ul> 170 * <li>Call {@link ActivityCompat#invalidateOptionsMenu(Activity)}. If the app is running 171 * on API level 11 or above and uses the Action Bar its menu will be recreated and rebuilt. 172 * If not, the activity will receive a call to {@link Activity#onPrepareOptionsMenu(Menu)} 173 * the next time the user presses the menu key to open the options menu panel. The activity 174 * can then call configureMenuItem again with a new or altered IntentBuilder to reconfigure 175 * the share menu item.</li> 176 * <li>Keep a reference to the MenuItem object for the share item once it has been created 177 * and call configureMenuItem to update the associated sharing intent as needed.</li> 178 * </ul> 179 * 180 * @param item MenuItem to configure for sharing 181 * @param shareIntent IntentBuilder with data about the content to share 182 */ 183 public static void configureMenuItem(MenuItem item, IntentBuilder shareIntent) { 184 IMPL.configureMenuItem(item, shareIntent); 185 } 186 187 /** 188 * Configure a menu item to act as a sharing action. 189 * 190 * @param menu Menu containing the item to use for sharing 191 * @param menuItemId ID of the share item within menu 192 * @param shareIntent IntentBuilder with data about the content to share 193 * @see #configureMenuItem(MenuItem, IntentBuilder) 194 */ 195 public static void configureMenuItem(Menu menu, int menuItemId, IntentBuilder shareIntent) { 196 MenuItem item = menu.findItem(menuItemId); 197 if (item == null) { 198 throw new IllegalArgumentException("Could not find menu item with id " + menuItemId + 199 " in the supplied menu"); 200 } 201 configureMenuItem(item, shareIntent); 202 } 203 204 /** 205 * IntentBuilder is a helper for constructing {@link Intent#ACTION_SEND} and 206 * {@link Intent#ACTION_SEND_MULTIPLE} sharing intents and starting activities 207 * to share content. The ComponentName and package name of the calling activity 208 * will be included. 209 */ 210 public static class IntentBuilder { 211 private Activity mActivity; 212 private Intent mIntent; 213 private CharSequence mChooserTitle; 214 private ArrayList<String> mToAddresses; 215 private ArrayList<String> mCcAddresses; 216 private ArrayList<String> mBccAddresses; 217 218 private ArrayList<Uri> mStreams; 219 220 /** 221 * Create a new IntentBuilder for launching a sharing action from launchingActivity. 222 * 223 * @param launchingActivity Activity that the share will be launched from 224 * @return a new IntentBuilder instance 225 */ 226 public static IntentBuilder from(Activity launchingActivity) { 227 return new IntentBuilder(launchingActivity); 228 } 229 230 private IntentBuilder(Activity launchingActivity) { 231 mActivity = launchingActivity; 232 mIntent = new Intent().setAction(Intent.ACTION_SEND); 233 mIntent.putExtra(EXTRA_CALLING_PACKAGE, launchingActivity.getPackageName()); 234 mIntent.putExtra(EXTRA_CALLING_ACTIVITY, launchingActivity.getComponentName()); 235 } 236 237 /** 238 * Retrieve the Intent as configured so far by the IntentBuilder. This Intent 239 * is suitable for use in a ShareActionProvider or chooser dialog. 240 * 241 * <p>To create an intent that will launch the activity chooser so that the user 242 * may select a target for the share, see {@link #createChooserIntent()}. 243 * 244 * @return The current Intent being configured by this builder 245 */ 246 public Intent getIntent() { 247 if (mToAddresses != null) { 248 combineArrayExtra(Intent.EXTRA_EMAIL, mToAddresses); 249 mToAddresses = null; 250 } 251 if (mCcAddresses != null) { 252 combineArrayExtra(Intent.EXTRA_CC, mCcAddresses); 253 mCcAddresses = null; 254 } 255 if (mBccAddresses != null) { 256 combineArrayExtra(Intent.EXTRA_BCC, mBccAddresses); 257 mBccAddresses = null; 258 } 259 260 // Check if we need to change the action. 261 boolean needsSendMultiple = mStreams != null && mStreams.size() > 1; 262 boolean isSendMultiple = mIntent.getAction().equals(Intent.ACTION_SEND_MULTIPLE); 263 264 if (!needsSendMultiple && isSendMultiple) { 265 // Change back to a single send action; place the first stream into the 266 // intent for single sharing. 267 mIntent.setAction(Intent.ACTION_SEND); 268 if (mStreams != null && !mStreams.isEmpty()) { 269 mIntent.putExtra(Intent.EXTRA_STREAM, mStreams.get(0)); 270 } else { 271 mIntent.removeExtra(Intent.EXTRA_STREAM); 272 } 273 mStreams = null; 274 } 275 276 if (needsSendMultiple && !isSendMultiple) { 277 // Change to a multiple send action; place the relevant ArrayList into the 278 // intent for multiple sharing. 279 mIntent.setAction(Intent.ACTION_SEND_MULTIPLE); 280 if (mStreams != null && !mStreams.isEmpty()) { 281 mIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, mStreams); 282 } else { 283 mIntent.removeExtra(Intent.EXTRA_STREAM); 284 } 285 } 286 287 return mIntent; 288 } 289 290 Activity getActivity() { 291 return mActivity; 292 } 293 294 private void combineArrayExtra(String extra, ArrayList<String> add) { 295 String[] currentAddresses = mIntent.getStringArrayExtra(extra); 296 int currentLength = currentAddresses != null ? currentAddresses.length : 0; 297 String[] finalAddresses = new String[currentLength + add.size()]; 298 add.toArray(finalAddresses); 299 if (currentAddresses != null) { 300 System.arraycopy(currentAddresses, 0, finalAddresses, add.size(), currentLength); 301 } 302 mIntent.putExtra(extra, finalAddresses); 303 } 304 305 private void combineArrayExtra(String extra, String[] add) { 306 // Add any items still pending 307 Intent intent = getIntent(); 308 String[] old = intent.getStringArrayExtra(extra); 309 int oldLength = old != null ? old.length : 0; 310 String[] result = new String[oldLength + add.length]; 311 if (old != null) System.arraycopy(old, 0, result, 0, oldLength); 312 System.arraycopy(add, 0, result, oldLength, add.length); 313 intent.putExtra(extra, result); 314 } 315 316 /** 317 * Create an Intent that will launch the standard Android activity chooser, 318 * allowing the user to pick what activity/app on the system should handle 319 * the share. 320 * 321 * @return A chooser Intent for the currently configured sharing action 322 */ 323 public Intent createChooserIntent() { 324 return Intent.createChooser(getIntent(), mChooserTitle); 325 } 326 327 /** 328 * Start a chooser activity for the current share intent for a result. 329 * The request code used will be {@link ShareCompat#REQUEST_CODE}. 330 */ 331 public void startChooserForResult() { 332 mActivity.startActivityForResult(createChooserIntent(), REQUEST_CODE); 333 } 334 335 /** 336 * Set the title that will be used for the activity chooser for this share. 337 * 338 * @param title Title string 339 * @return This IntentBuilder for method chaining 340 */ 341 public IntentBuilder setChooserTitle(CharSequence title) { 342 mChooserTitle = title; 343 return this; 344 } 345 346 /** 347 * Set the title that will be used for the activity chooser for this share. 348 * 349 * @param resId Resource ID of the title string to use 350 * @return This IntentBuilder for method chaining 351 */ 352 public IntentBuilder setChooserTitle(int resId) { 353 return setChooserTitle(mActivity.getText(resId)); 354 } 355 356 /** 357 * Set the type of data being shared 358 * 359 * @param mimeType mimetype of the shared data 360 * @return This IntentBuilder for method chaining 361 * @see Intent#setType(String) 362 */ 363 public IntentBuilder setType(String mimeType) { 364 mIntent.setType(mimeType); 365 return this; 366 } 367 368 /** 369 * Set the literal text data to be sent as part of the share. 370 * 371 * @param text Text to share 372 * @return This IntentBuilder for method chaining 373 * @see Intent#EXTRA_TEXT 374 */ 375 public IntentBuilder setText(CharSequence text) { 376 mIntent.putExtra(Intent.EXTRA_TEXT, text); 377 return this; 378 } 379 380 /** 381 * Set a stream URI to the data that should be shared. 382 * 383 * <p>This replaces all currently set stream URIs and will produce a single-stream 384 * ACTION_SEND intent.</p> 385 * 386 * @param streamUri URI of the stream to share 387 * @return This IntentBuilder for method chaining 388 * @see Intent#EXTRA_STREAM 389 */ 390 public IntentBuilder setStream(Uri streamUri) { 391 if (!mIntent.getAction().equals(Intent.ACTION_SEND)) { 392 mIntent.setAction(Intent.ACTION_SEND); 393 } 394 mStreams = null; 395 mIntent.putExtra(Intent.EXTRA_STREAM, streamUri); 396 return this; 397 } 398 399 /** 400 * Add a stream URI to the data that should be shared. If this is not the first 401 * stream URI added the final intent constructed will become an ACTION_SEND_MULTIPLE 402 * intent. Not all apps will handle both ACTION_SEND and ACTION_SEND_MULTIPLE. 403 * 404 * @param streamUri URI of the stream to share 405 * @return This IntentBuilder for method chaining 406 * @see Intent#EXTRA_STREAM 407 * @see Intent#ACTION_SEND 408 * @see Intent#ACTION_SEND_MULTIPLE 409 */ 410 public IntentBuilder addStream(Uri streamUri) { 411 Uri currentStream = mIntent.getParcelableExtra(Intent.EXTRA_STREAM); 412 if (currentStream == null) { 413 return setStream(streamUri); 414 } 415 if (mStreams == null) { 416 mStreams = new ArrayList<Uri>(); 417 } 418 if (currentStream != null) { 419 mIntent.removeExtra(Intent.EXTRA_STREAM); 420 mStreams.add(currentStream); 421 } 422 mStreams.add(streamUri); 423 return this; 424 } 425 426 /** 427 * Set an array of email addresses as recipients of this share. 428 * This replaces all current "to" recipients that have been set so far. 429 * 430 * @param addresses Email addresses to send to 431 * @return This IntentBuilder for method chaining 432 * @see Intent#EXTRA_EMAIL 433 */ 434 public IntentBuilder setEmailTo(String[] addresses) { 435 if (mToAddresses != null) { 436 mToAddresses = null; 437 } 438 mIntent.putExtra(Intent.EXTRA_EMAIL, addresses); 439 return this; 440 } 441 442 /** 443 * Add an email address to be used in the "to" field of the final Intent. 444 * 445 * @param address Email address to send to 446 * @return This IntentBuilder for method chaining 447 * @see Intent#EXTRA_EMAIL 448 */ 449 public IntentBuilder addEmailTo(String address) { 450 if (mToAddresses == null) { 451 mToAddresses = new ArrayList<String>(); 452 } 453 mToAddresses.add(address); 454 return this; 455 } 456 457 /** 458 * Add an array of email addresses to be used in the "to" field of the final Intent. 459 * 460 * @param addresses Email addresses to send to 461 * @return This IntentBuilder for method chaining 462 * @see Intent#EXTRA_EMAIL 463 */ 464 public IntentBuilder addEmailTo(String[] addresses) { 465 combineArrayExtra(Intent.EXTRA_EMAIL, addresses); 466 return this; 467 } 468 469 /** 470 * Set an array of email addresses to CC on this share. 471 * This replaces all current "CC" recipients that have been set so far. 472 * 473 * @param addresses Email addresses to CC on the share 474 * @return This IntentBuilder for method chaining 475 * @see Intent#EXTRA_CC 476 */ 477 public IntentBuilder setEmailCc(String[] addresses) { 478 mIntent.putExtra(Intent.EXTRA_CC, addresses); 479 return this; 480 } 481 482 /** 483 * Add an email address to be used in the "cc" field of the final Intent. 484 * 485 * @param address Email address to CC 486 * @return This IntentBuilder for method chaining 487 * @see Intent#EXTRA_CC 488 */ 489 public IntentBuilder addEmailCc(String address) { 490 if (mCcAddresses == null) { 491 mCcAddresses = new ArrayList<String>(); 492 } 493 mCcAddresses.add(address); 494 return this; 495 } 496 497 /** 498 * Add an array of email addresses to be used in the "cc" field of the final Intent. 499 * 500 * @param addresses Email addresses to CC 501 * @return This IntentBuilder for method chaining 502 * @see Intent#EXTRA_CC 503 */ 504 public IntentBuilder addEmailCc(String[] addresses) { 505 combineArrayExtra(Intent.EXTRA_CC, addresses); 506 return this; 507 } 508 509 /** 510 * Set an array of email addresses to BCC on this share. 511 * This replaces all current "BCC" recipients that have been set so far. 512 * 513 * @param addresses Email addresses to BCC on the share 514 * @return This IntentBuilder for method chaining 515 * @see Intent#EXTRA_BCC 516 */ 517 public IntentBuilder setEmailBcc(String[] addresses) { 518 mIntent.putExtra(Intent.EXTRA_BCC, addresses); 519 return this; 520 } 521 522 /** 523 * Add an email address to be used in the "bcc" field of the final Intent. 524 * 525 * @param address Email address to BCC 526 * @return This IntentBuilder for method chaining 527 * @see Intent#EXTRA_BCC 528 */ 529 public IntentBuilder addEmailBcc(String address) { 530 if (mBccAddresses == null) { 531 mBccAddresses = new ArrayList<String>(); 532 } 533 mBccAddresses.add(address); 534 return this; 535 } 536 537 /** 538 * Add an array of email addresses to be used in the "bcc" field of the final Intent. 539 * 540 * @param addresses Email addresses to BCC 541 * @return This IntentBuilder for method chaining 542 * @see Intent#EXTRA_BCC 543 */ 544 public IntentBuilder addEmailBcc(String[] addresses) { 545 combineArrayExtra(Intent.EXTRA_BCC, addresses); 546 return this; 547 } 548 549 /** 550 * Set a subject heading for this share; useful for sharing via email. 551 * 552 * @param subject Subject heading for this share 553 * @return This IntentBuilder for method chaining 554 * @see Intent#EXTRA_SUBJECT 555 */ 556 public IntentBuilder setSubject(String subject) { 557 mIntent.putExtra(Intent.EXTRA_SUBJECT, subject); 558 return this; 559 } 560 } 561 562 /** 563 * IntentReader is a helper for reading the data contained within a sharing (ACTION_SEND) 564 * Intent. It provides methods to parse standard elements included with a share 565 * in addition to extra metadata about the app that shared the content. 566 * 567 * <p>Social sharing apps are encouraged to provide attribution for the app that shared 568 * the content. IntentReader offers access to the application label, calling activity info, 569 * and application icon of the app that shared the content. This data may have been provided 570 * voluntarily by the calling app and should always be displayed to the user before submission 571 * for manual verification. The user should be offered the option to omit this information 572 * from shared posts if desired.</p> 573 * 574 * <p>Activities that intend to receive sharing intents should configure an intent-filter 575 * to accept {@link Intent#ACTION_SEND} intents ("android.intent.action.SEND") and optionally 576 * accept {@link Intent#ACTION_SEND_MULTIPLE} ("android.intent.action.SEND_MULTIPLE") if 577 * the activity is equipped to handle multiple data streams.</p> 578 */ 579 public static class IntentReader { 580 private static final String TAG = "IntentReader"; 581 582 private Activity mActivity; 583 private Intent mIntent; 584 private String mCallingPackage; 585 private ComponentName mCallingActivity; 586 587 private ArrayList<Uri> mStreams; 588 589 /** 590 * Get an IntentReader for parsing and interpreting the sharing intent 591 * used to start the given activity. 592 * 593 * @param activity Activity that was started to share content 594 * @return IntentReader for parsing sharing data 595 */ 596 public static IntentReader from(Activity activity) { 597 return new IntentReader(activity); 598 } 599 600 private IntentReader(Activity activity) { 601 mActivity = activity; 602 mIntent = activity.getIntent(); 603 mCallingPackage = ShareCompat.getCallingPackage(activity); 604 mCallingActivity = ShareCompat.getCallingActivity(activity); 605 } 606 607 /** 608 * Returns true if the activity this reader was obtained for was 609 * started with an {@link Intent#ACTION_SEND} or {@link Intent#ACTION_SEND_MULTIPLE} 610 * sharing Intent. 611 * 612 * @return true if the activity was started with an ACTION_SEND 613 * or ACTION_SEND_MULTIPLE Intent 614 */ 615 public boolean isShareIntent() { 616 final String action = mIntent.getAction(); 617 return action.equals(Intent.ACTION_SEND) || action.equals(Intent.ACTION_SEND_MULTIPLE); 618 } 619 620 /** 621 * Returns true if the activity this reader was obtained for was started with an 622 * {@link Intent#ACTION_SEND} intent and contains a single shared item. 623 * The shared content should be obtained using either the {@link #getText()} 624 * or {@link #getStream()} methods depending on the type of content shared. 625 * 626 * @return true if the activity was started with an ACTION_SEND intent 627 */ 628 public boolean isSingleShare() { 629 return mIntent.getAction().equals(Intent.ACTION_SEND); 630 } 631 632 /** 633 * Returns true if the activity this reader was obtained for was started with an 634 * {@link Intent#ACTION_SEND_MULTIPLE} intent. The Intent may contain more than 635 * one stream item. 636 * 637 * @return true if the activity was started with an ACTION_SEND_MULTIPLE intent 638 */ 639 public boolean isMultipleShare() { 640 return mIntent.getAction().equals(Intent.ACTION_SEND_MULTIPLE); 641 } 642 643 /** 644 * Get the mimetype of the data shared to this activity. 645 * 646 * @return mimetype of the shared data 647 * @see Intent#getType() 648 */ 649 public String getType() { 650 return mIntent.getType(); 651 } 652 653 /** 654 * Get the literal text shared with the target activity. 655 * 656 * @return Literal shared text or null if none was supplied 657 * @see Intent#EXTRA_TEXT 658 */ 659 public CharSequence getText() { 660 return mIntent.getCharSequenceExtra(Intent.EXTRA_TEXT); 661 } 662 663 /** 664 * Get a URI referring to a data stream shared with the target activity. 665 * 666 * <p>This call will fail if the share intent contains multiple stream items. 667 * If {@link #isMultipleShare()} returns true the application should use 668 * {@link #getStream(int)} and {@link #getStreamCount()} to retrieve the 669 * included stream items.</p> 670 * 671 * @return A URI referring to a data stream to be shared or null if one was not supplied 672 * @see Intent#EXTRA_STREAM 673 */ 674 public Uri getStream() { 675 return mIntent.getParcelableExtra(Intent.EXTRA_STREAM); 676 } 677 678 /** 679 * Get the URI of a stream item shared with the target activity. 680 * Index should be in the range [0-getStreamCount()). 681 * 682 * @param index Index of text item to retrieve 683 * @return Requested stream item URI 684 * @see Intent#EXTRA_STREAM 685 * @see Intent#ACTION_SEND_MULTIPLE 686 */ 687 public Uri getStream(int index) { 688 if (mStreams == null && isMultipleShare()) { 689 mStreams = mIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); 690 } 691 if (mStreams != null) { 692 return mStreams.get(index); 693 } 694 if (index == 0) { 695 return mIntent.getParcelableExtra(Intent.EXTRA_STREAM); 696 } 697 throw new IndexOutOfBoundsException("Stream items available: " + getStreamCount() + 698 " index requested: " + index); 699 } 700 701 /** 702 * Return the number of stream items shared. The return value will be 0 or 1 if 703 * this was an {@link Intent#ACTION_SEND} intent, or 0 or more if it was an 704 * {@link Intent#ACTION_SEND_MULTIPLE} intent. 705 * 706 * @return Count of text items contained within the Intent 707 */ 708 public int getStreamCount() { 709 if (mStreams == null && isMultipleShare()) { 710 mStreams = mIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); 711 } 712 if (mStreams != null) { 713 return mStreams.size(); 714 } 715 return mIntent.hasExtra(Intent.EXTRA_STREAM) ? 1 : 0; 716 } 717 718 /** 719 * Get an array of Strings, each an email address to share to. 720 * 721 * @return An array of email addresses or null if none were supplied. 722 * @see Intent#EXTRA_EMAIL 723 */ 724 public String[] getEmailTo() { 725 return mIntent.getStringArrayExtra(Intent.EXTRA_EMAIL); 726 } 727 728 /** 729 * Get an array of Strings, each an email address to CC on this share. 730 * 731 * @return An array of email addresses or null if none were supplied. 732 * @see Intent#EXTRA_CC 733 */ 734 public String[] getEmailCc() { 735 return mIntent.getStringArrayExtra(Intent.EXTRA_CC); 736 } 737 738 /** 739 * Get an array of Strings, each an email address to BCC on this share. 740 * 741 * @return An array of email addresses or null if none were supplied. 742 * @see Intent#EXTRA_BCC 743 */ 744 public String[] getEmailBcc() { 745 return mIntent.getStringArrayExtra(Intent.EXTRA_BCC); 746 } 747 748 /** 749 * Get a subject heading for this share; useful when sharing via email. 750 * 751 * @return The subject heading for this share or null if one was not supplied. 752 * @see Intent#EXTRA_SUBJECT 753 */ 754 public String getSubject() { 755 return mIntent.getStringExtra(Intent.EXTRA_SUBJECT); 756 } 757 758 /** 759 * Get the name of the package that invoked this sharing intent. If the activity 760 * was not started for a result, IntentBuilder will read this from extra metadata placed 761 * in the Intent by ShareBuilder. 762 * 763 * <p><em>Note:</em> This data may have been provided voluntarily by the calling 764 * application. As such it should not be trusted for accuracy in the context of 765 * security or verification.</p> 766 * 767 * @return Name of the package that started this activity or null if unknown 768 * @see Activity#getCallingPackage() 769 * @see ShareCompat#EXTRA_CALLING_PACKAGE 770 */ 771 public String getCallingPackage() { 772 return mCallingPackage; 773 } 774 775 /** 776 * Get the {@link ComponentName} of the Activity that invoked this sharing intent. 777 * If the target sharing activity was not started for a result, IntentBuilder will read 778 * this from extra metadata placed in the intent by ShareBuilder. 779 * 780 * <p><em>Note:</em> This data may have been provided voluntarily by the calling 781 * application. As such it should not be trusted for accuracy in the context of 782 * security or verification.</p> 783 * 784 * @return ComponentName of the calling Activity or null if unknown 785 * @see Activity#getCallingActivity() 786 * @see ShareCompat#EXTRA_CALLING_ACTIVITY 787 */ 788 public ComponentName getCallingActivity() { 789 return mCallingActivity; 790 } 791 792 /** 793 * Get the icon of the calling activity as a Drawable if data about 794 * the calling activity is available. 795 * 796 * <p><em>Note:</em> This data may have been provided voluntarily by the calling 797 * application. As such it should not be trusted for accuracy in the context of 798 * security or verification.</p> 799 * 800 * @return The calling Activity's icon or null if unknown 801 */ 802 public Drawable getCallingActivityIcon() { 803 if (mCallingActivity == null) return null; 804 805 PackageManager pm = mActivity.getPackageManager(); 806 try { 807 return pm.getActivityIcon(mCallingActivity); 808 } catch (NameNotFoundException e) { 809 Log.e(TAG, "Could not retrieve icon for calling activity", e); 810 } 811 return null; 812 } 813 814 /** 815 * Get the icon of the calling application as a Drawable if data 816 * about the calling package is available. 817 * 818 * <p><em>Note:</em> This data may have been provided voluntarily by the calling 819 * application. As such it should not be trusted for accuracy in the context of 820 * security or verification.</p> 821 * 822 * @return The calling application's icon or null if unknown 823 */ 824 public Drawable getCallingApplicationIcon() { 825 if (mCallingPackage == null) return null; 826 827 PackageManager pm = mActivity.getPackageManager(); 828 try { 829 return pm.getApplicationIcon(mCallingPackage); 830 } catch (NameNotFoundException e) { 831 Log.e(TAG, "Could not retrieve icon for calling application", e); 832 } 833 return null; 834 } 835 836 /** 837 * Get the human-readable label (title) of the calling application if 838 * data about the calling package is available. 839 * 840 * <p><em>Note:</em> This data may have been provided voluntarily by the calling 841 * application. As such it should not be trusted for accuracy in the context of 842 * security or verification.</p> 843 * 844 * @return The calling application's label or null if unknown 845 */ 846 public CharSequence getCallingApplicationLabel() { 847 if (mCallingPackage == null) return null; 848 849 PackageManager pm = mActivity.getPackageManager(); 850 try { 851 return pm.getApplicationLabel(pm.getApplicationInfo(mCallingPackage, 0)); 852 } catch (NameNotFoundException e) { 853 Log.e(TAG, "Could not retrieve label for calling application", e); 854 } 855 return null; 856 } 857 } 858} 859