ShareCompat.java revision 8650b2be627ebfe5b2625fae69624652ce0d7de0
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 mIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 236 } 237 238 /** 239 * Retrieve the Intent as configured so far by the IntentBuilder. This Intent 240 * is suitable for use in a ShareActionProvider or chooser dialog. 241 * 242 * <p>To create an intent that will launch the activity chooser so that the user 243 * may select a target for the share, see {@link #createChooserIntent()}. 244 * 245 * @return The current Intent being configured by this builder 246 */ 247 public Intent getIntent() { 248 if (mToAddresses != null) { 249 combineArrayExtra(Intent.EXTRA_EMAIL, mToAddresses); 250 mToAddresses = null; 251 } 252 if (mCcAddresses != null) { 253 combineArrayExtra(Intent.EXTRA_CC, mCcAddresses); 254 mCcAddresses = null; 255 } 256 if (mBccAddresses != null) { 257 combineArrayExtra(Intent.EXTRA_BCC, mBccAddresses); 258 mBccAddresses = null; 259 } 260 261 // Check if we need to change the action. 262 boolean needsSendMultiple = mStreams != null && mStreams.size() > 1; 263 boolean isSendMultiple = mIntent.getAction().equals(Intent.ACTION_SEND_MULTIPLE); 264 265 if (!needsSendMultiple && isSendMultiple) { 266 // Change back to a single send action; place the first stream into the 267 // intent for single sharing. 268 mIntent.setAction(Intent.ACTION_SEND); 269 if (mStreams != null && !mStreams.isEmpty()) { 270 mIntent.putExtra(Intent.EXTRA_STREAM, mStreams.get(0)); 271 } else { 272 mIntent.removeExtra(Intent.EXTRA_STREAM); 273 } 274 mStreams = null; 275 } 276 277 if (needsSendMultiple && !isSendMultiple) { 278 // Change to a multiple send action; place the relevant ArrayList into the 279 // intent for multiple sharing. 280 mIntent.setAction(Intent.ACTION_SEND_MULTIPLE); 281 if (mStreams != null && !mStreams.isEmpty()) { 282 mIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, mStreams); 283 } else { 284 mIntent.removeExtra(Intent.EXTRA_STREAM); 285 } 286 } 287 288 return mIntent; 289 } 290 291 Activity getActivity() { 292 return mActivity; 293 } 294 295 private void combineArrayExtra(String extra, ArrayList<String> add) { 296 String[] currentAddresses = mIntent.getStringArrayExtra(extra); 297 int currentLength = currentAddresses != null ? currentAddresses.length : 0; 298 String[] finalAddresses = new String[currentLength + add.size()]; 299 add.toArray(finalAddresses); 300 if (currentAddresses != null) { 301 System.arraycopy(currentAddresses, 0, finalAddresses, add.size(), currentLength); 302 } 303 mIntent.putExtra(extra, finalAddresses); 304 } 305 306 private void combineArrayExtra(String extra, String[] add) { 307 // Add any items still pending 308 Intent intent = getIntent(); 309 String[] old = intent.getStringArrayExtra(extra); 310 int oldLength = old != null ? old.length : 0; 311 String[] result = new String[oldLength + add.length]; 312 if (old != null) System.arraycopy(old, 0, result, 0, oldLength); 313 System.arraycopy(add, 0, result, oldLength, add.length); 314 intent.putExtra(extra, result); 315 } 316 317 /** 318 * Create an Intent that will launch the standard Android activity chooser, 319 * allowing the user to pick what activity/app on the system should handle 320 * the share. 321 * 322 * @return A chooser Intent for the currently configured sharing action 323 */ 324 public Intent createChooserIntent() { 325 return Intent.createChooser(getIntent(), mChooserTitle); 326 } 327 328 /** 329 * Start a chooser activity for the current share intent for a result. 330 * The request code used will be {@link ShareCompat#REQUEST_CODE}. 331 */ 332 public void startChooserForResult() { 333 mActivity.startActivityForResult(createChooserIntent(), REQUEST_CODE); 334 } 335 336 /** 337 * Set the title that will be used for the activity chooser for this share. 338 * 339 * @param title Title string 340 * @return This IntentBuilder for method chaining 341 */ 342 public IntentBuilder setChooserTitle(CharSequence title) { 343 mChooserTitle = title; 344 return this; 345 } 346 347 /** 348 * Set the title that will be used for the activity chooser for this share. 349 * 350 * @param resId Resource ID of the title string to use 351 * @return This IntentBuilder for method chaining 352 */ 353 public IntentBuilder setChooserTitle(int resId) { 354 return setChooserTitle(mActivity.getText(resId)); 355 } 356 357 /** 358 * Set the type of data being shared 359 * 360 * @param mimeType mimetype of the shared data 361 * @return This IntentBuilder for method chaining 362 * @see Intent#setType(String) 363 */ 364 public IntentBuilder setType(String mimeType) { 365 mIntent.setType(mimeType); 366 return this; 367 } 368 369 /** 370 * Set the literal text data to be sent as part of the share. 371 * 372 * @param text Text to share 373 * @return This IntentBuilder for method chaining 374 * @see Intent#EXTRA_TEXT 375 */ 376 public IntentBuilder setText(CharSequence text) { 377 mIntent.putExtra(Intent.EXTRA_TEXT, text); 378 return this; 379 } 380 381 /** 382 * Set a stream URI to the data that should be shared. 383 * 384 * <p>This replaces all currently set stream URIs and will produce a single-stream 385 * ACTION_SEND intent.</p> 386 * 387 * @param streamUri URI of the stream to share 388 * @return This IntentBuilder for method chaining 389 * @see Intent#EXTRA_STREAM 390 */ 391 public IntentBuilder setStream(Uri streamUri) { 392 if (!mIntent.getAction().equals(Intent.ACTION_SEND)) { 393 mIntent.setAction(Intent.ACTION_SEND); 394 } 395 mStreams = null; 396 mIntent.putExtra(Intent.EXTRA_STREAM, streamUri); 397 return this; 398 } 399 400 /** 401 * Add a stream URI to the data that should be shared. If this is not the first 402 * stream URI added the final intent constructed will become an ACTION_SEND_MULTIPLE 403 * intent. Not all apps will handle both ACTION_SEND and ACTION_SEND_MULTIPLE. 404 * 405 * @param streamUri URI of the stream to share 406 * @return This IntentBuilder for method chaining 407 * @see Intent#EXTRA_STREAM 408 * @see Intent#ACTION_SEND 409 * @see Intent#ACTION_SEND_MULTIPLE 410 */ 411 public IntentBuilder addStream(Uri streamUri) { 412 Uri currentStream = mIntent.getParcelableExtra(Intent.EXTRA_STREAM); 413 if (currentStream == null) { 414 return setStream(streamUri); 415 } 416 if (mStreams == null) { 417 mStreams = new ArrayList<Uri>(); 418 } 419 if (currentStream != null) { 420 mIntent.removeExtra(Intent.EXTRA_STREAM); 421 mStreams.add(currentStream); 422 } 423 mStreams.add(streamUri); 424 return this; 425 } 426 427 /** 428 * Set an array of email addresses as recipients of this share. 429 * This replaces all current "to" recipients that have been set so far. 430 * 431 * @param addresses Email addresses to send to 432 * @return This IntentBuilder for method chaining 433 * @see Intent#EXTRA_EMAIL 434 */ 435 public IntentBuilder setEmailTo(String[] addresses) { 436 if (mToAddresses != null) { 437 mToAddresses = null; 438 } 439 mIntent.putExtra(Intent.EXTRA_EMAIL, addresses); 440 return this; 441 } 442 443 /** 444 * Add an email address to be used in the "to" field of the final Intent. 445 * 446 * @param address Email address to send to 447 * @return This IntentBuilder for method chaining 448 * @see Intent#EXTRA_EMAIL 449 */ 450 public IntentBuilder addEmailTo(String address) { 451 if (mToAddresses == null) { 452 mToAddresses = new ArrayList<String>(); 453 } 454 mToAddresses.add(address); 455 return this; 456 } 457 458 /** 459 * Add an array of email addresses to be used in the "to" field of the final Intent. 460 * 461 * @param addresses Email addresses to send to 462 * @return This IntentBuilder for method chaining 463 * @see Intent#EXTRA_EMAIL 464 */ 465 public IntentBuilder addEmailTo(String[] addresses) { 466 combineArrayExtra(Intent.EXTRA_EMAIL, addresses); 467 return this; 468 } 469 470 /** 471 * Set an array of email addresses to CC on this share. 472 * This replaces all current "CC" recipients that have been set so far. 473 * 474 * @param addresses Email addresses to CC on the share 475 * @return This IntentBuilder for method chaining 476 * @see Intent#EXTRA_CC 477 */ 478 public IntentBuilder setEmailCc(String[] addresses) { 479 mIntent.putExtra(Intent.EXTRA_CC, addresses); 480 return this; 481 } 482 483 /** 484 * Add an email address to be used in the "cc" field of the final Intent. 485 * 486 * @param address Email address to CC 487 * @return This IntentBuilder for method chaining 488 * @see Intent#EXTRA_CC 489 */ 490 public IntentBuilder addEmailCc(String address) { 491 if (mCcAddresses == null) { 492 mCcAddresses = new ArrayList<String>(); 493 } 494 mCcAddresses.add(address); 495 return this; 496 } 497 498 /** 499 * Add an array of email addresses to be used in the "cc" field of the final Intent. 500 * 501 * @param addresses Email addresses to CC 502 * @return This IntentBuilder for method chaining 503 * @see Intent#EXTRA_CC 504 */ 505 public IntentBuilder addEmailCc(String[] addresses) { 506 combineArrayExtra(Intent.EXTRA_CC, addresses); 507 return this; 508 } 509 510 /** 511 * Set an array of email addresses to BCC on this share. 512 * This replaces all current "BCC" recipients that have been set so far. 513 * 514 * @param addresses Email addresses to BCC on the share 515 * @return This IntentBuilder for method chaining 516 * @see Intent#EXTRA_BCC 517 */ 518 public IntentBuilder setEmailBcc(String[] addresses) { 519 mIntent.putExtra(Intent.EXTRA_BCC, addresses); 520 return this; 521 } 522 523 /** 524 * Add an email address to be used in the "bcc" field of the final Intent. 525 * 526 * @param address Email address to BCC 527 * @return This IntentBuilder for method chaining 528 * @see Intent#EXTRA_BCC 529 */ 530 public IntentBuilder addEmailBcc(String address) { 531 if (mBccAddresses == null) { 532 mBccAddresses = new ArrayList<String>(); 533 } 534 mBccAddresses.add(address); 535 return this; 536 } 537 538 /** 539 * Add an array of email addresses to be used in the "bcc" field of the final Intent. 540 * 541 * @param addresses Email addresses to BCC 542 * @return This IntentBuilder for method chaining 543 * @see Intent#EXTRA_BCC 544 */ 545 public IntentBuilder addEmailBcc(String[] addresses) { 546 combineArrayExtra(Intent.EXTRA_BCC, addresses); 547 return this; 548 } 549 550 /** 551 * Set a subject heading for this share; useful for sharing via email. 552 * 553 * @param subject Subject heading for this share 554 * @return This IntentBuilder for method chaining 555 * @see Intent#EXTRA_SUBJECT 556 */ 557 public IntentBuilder setSubject(String subject) { 558 mIntent.putExtra(Intent.EXTRA_SUBJECT, subject); 559 return this; 560 } 561 } 562 563 /** 564 * IntentReader is a helper for reading the data contained within a sharing (ACTION_SEND) 565 * Intent. It provides methods to parse standard elements included with a share 566 * in addition to extra metadata about the app that shared the content. 567 * 568 * <p>Social sharing apps are encouraged to provide attribution for the app that shared 569 * the content. IntentReader offers access to the application label, calling activity info, 570 * and application icon of the app that shared the content. This data may have been provided 571 * voluntarily by the calling app and should always be displayed to the user before submission 572 * for manual verification. The user should be offered the option to omit this information 573 * from shared posts if desired.</p> 574 * 575 * <p>Activities that intend to receive sharing intents should configure an intent-filter 576 * to accept {@link Intent#ACTION_SEND} intents ("android.intent.action.SEND") and optionally 577 * accept {@link Intent#ACTION_SEND_MULTIPLE} ("android.intent.action.SEND_MULTIPLE") if 578 * the activity is equipped to handle multiple data streams.</p> 579 */ 580 public static class IntentReader { 581 private static final String TAG = "IntentReader"; 582 583 private Activity mActivity; 584 private Intent mIntent; 585 private String mCallingPackage; 586 private ComponentName mCallingActivity; 587 588 private ArrayList<Uri> mStreams; 589 590 /** 591 * Get an IntentReader for parsing and interpreting the sharing intent 592 * used to start the given activity. 593 * 594 * @param activity Activity that was started to share content 595 * @return IntentReader for parsing sharing data 596 */ 597 public static IntentReader from(Activity activity) { 598 return new IntentReader(activity); 599 } 600 601 private IntentReader(Activity activity) { 602 mActivity = activity; 603 mIntent = activity.getIntent(); 604 mCallingPackage = ShareCompat.getCallingPackage(activity); 605 mCallingActivity = ShareCompat.getCallingActivity(activity); 606 } 607 608 /** 609 * Returns true if the activity this reader was obtained for was 610 * started with an {@link Intent#ACTION_SEND} or {@link Intent#ACTION_SEND_MULTIPLE} 611 * sharing Intent. 612 * 613 * @return true if the activity was started with an ACTION_SEND 614 * or ACTION_SEND_MULTIPLE Intent 615 */ 616 public boolean isShareIntent() { 617 final String action = mIntent.getAction(); 618 return action.equals(Intent.ACTION_SEND) || action.equals(Intent.ACTION_SEND_MULTIPLE); 619 } 620 621 /** 622 * Returns true if the activity this reader was obtained for was started with an 623 * {@link Intent#ACTION_SEND} intent and contains a single shared item. 624 * The shared content should be obtained using either the {@link #getText()} 625 * or {@link #getStream()} methods depending on the type of content shared. 626 * 627 * @return true if the activity was started with an ACTION_SEND intent 628 */ 629 public boolean isSingleShare() { 630 return mIntent.getAction().equals(Intent.ACTION_SEND); 631 } 632 633 /** 634 * Returns true if the activity this reader was obtained for was started with an 635 * {@link Intent#ACTION_SEND_MULTIPLE} intent. The Intent may contain more than 636 * one stream item. 637 * 638 * @return true if the activity was started with an ACTION_SEND_MULTIPLE intent 639 */ 640 public boolean isMultipleShare() { 641 return mIntent.getAction().equals(Intent.ACTION_SEND_MULTIPLE); 642 } 643 644 /** 645 * Get the mimetype of the data shared to this activity. 646 * 647 * @return mimetype of the shared data 648 * @see Intent#getType() 649 */ 650 public String getType() { 651 return mIntent.getType(); 652 } 653 654 /** 655 * Get the literal text shared with the target activity. 656 * 657 * @return Literal shared text or null if none was supplied 658 * @see Intent#EXTRA_TEXT 659 */ 660 public CharSequence getText() { 661 return mIntent.getCharSequenceExtra(Intent.EXTRA_TEXT); 662 } 663 664 /** 665 * Get a URI referring to a data stream shared with the target activity. 666 * 667 * <p>This call will fail if the share intent contains multiple stream items. 668 * If {@link #isMultipleShare()} returns true the application should use 669 * {@link #getStream(int)} and {@link #getStreamCount()} to retrieve the 670 * included stream items.</p> 671 * 672 * @return A URI referring to a data stream to be shared or null if one was not supplied 673 * @see Intent#EXTRA_STREAM 674 */ 675 public Uri getStream() { 676 return mIntent.getParcelableExtra(Intent.EXTRA_STREAM); 677 } 678 679 /** 680 * Get the URI of a stream item shared with the target activity. 681 * Index should be in the range [0-getStreamCount()). 682 * 683 * @param index Index of text item to retrieve 684 * @return Requested stream item URI 685 * @see Intent#EXTRA_STREAM 686 * @see Intent#ACTION_SEND_MULTIPLE 687 */ 688 public Uri getStream(int index) { 689 if (mStreams == null && isMultipleShare()) { 690 mStreams = mIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); 691 } 692 if (mStreams != null) { 693 return mStreams.get(index); 694 } 695 if (index == 0) { 696 return mIntent.getParcelableExtra(Intent.EXTRA_STREAM); 697 } 698 throw new IndexOutOfBoundsException("Stream items available: " + getStreamCount() + 699 " index requested: " + index); 700 } 701 702 /** 703 * Return the number of stream items shared. The return value will be 0 or 1 if 704 * this was an {@link Intent#ACTION_SEND} intent, or 0 or more if it was an 705 * {@link Intent#ACTION_SEND_MULTIPLE} intent. 706 * 707 * @return Count of text items contained within the Intent 708 */ 709 public int getStreamCount() { 710 if (mStreams == null && isMultipleShare()) { 711 mStreams = mIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); 712 } 713 if (mStreams != null) { 714 return mStreams.size(); 715 } 716 return mIntent.hasExtra(Intent.EXTRA_STREAM) ? 1 : 0; 717 } 718 719 /** 720 * Get an array of Strings, each an email address to share to. 721 * 722 * @return An array of email addresses or null if none were supplied. 723 * @see Intent#EXTRA_EMAIL 724 */ 725 public String[] getEmailTo() { 726 return mIntent.getStringArrayExtra(Intent.EXTRA_EMAIL); 727 } 728 729 /** 730 * Get an array of Strings, each an email address to CC on this share. 731 * 732 * @return An array of email addresses or null if none were supplied. 733 * @see Intent#EXTRA_CC 734 */ 735 public String[] getEmailCc() { 736 return mIntent.getStringArrayExtra(Intent.EXTRA_CC); 737 } 738 739 /** 740 * Get an array of Strings, each an email address to BCC on this share. 741 * 742 * @return An array of email addresses or null if none were supplied. 743 * @see Intent#EXTRA_BCC 744 */ 745 public String[] getEmailBcc() { 746 return mIntent.getStringArrayExtra(Intent.EXTRA_BCC); 747 } 748 749 /** 750 * Get a subject heading for this share; useful when sharing via email. 751 * 752 * @return The subject heading for this share or null if one was not supplied. 753 * @see Intent#EXTRA_SUBJECT 754 */ 755 public String getSubject() { 756 return mIntent.getStringExtra(Intent.EXTRA_SUBJECT); 757 } 758 759 /** 760 * Get the name of the package that invoked this sharing intent. If the activity 761 * was not started for a result, IntentBuilder will read this from extra metadata placed 762 * in the Intent by ShareBuilder. 763 * 764 * <p><em>Note:</em> This data may have been provided voluntarily by the calling 765 * application. As such it should not be trusted for accuracy in the context of 766 * security or verification.</p> 767 * 768 * @return Name of the package that started this activity or null if unknown 769 * @see Activity#getCallingPackage() 770 * @see ShareCompat#EXTRA_CALLING_PACKAGE 771 */ 772 public String getCallingPackage() { 773 return mCallingPackage; 774 } 775 776 /** 777 * Get the {@link ComponentName} of the Activity that invoked this sharing intent. 778 * If the target sharing activity was not started for a result, IntentBuilder will read 779 * this from extra metadata placed in the intent by ShareBuilder. 780 * 781 * <p><em>Note:</em> This data may have been provided voluntarily by the calling 782 * application. As such it should not be trusted for accuracy in the context of 783 * security or verification.</p> 784 * 785 * @return ComponentName of the calling Activity or null if unknown 786 * @see Activity#getCallingActivity() 787 * @see ShareCompat#EXTRA_CALLING_ACTIVITY 788 */ 789 public ComponentName getCallingActivity() { 790 return mCallingActivity; 791 } 792 793 /** 794 * Get the icon of the calling activity as a Drawable if data about 795 * the calling activity is available. 796 * 797 * <p><em>Note:</em> This data may have been provided voluntarily by the calling 798 * application. As such it should not be trusted for accuracy in the context of 799 * security or verification.</p> 800 * 801 * @return The calling Activity's icon or null if unknown 802 */ 803 public Drawable getCallingActivityIcon() { 804 if (mCallingActivity == null) return null; 805 806 PackageManager pm = mActivity.getPackageManager(); 807 try { 808 return pm.getActivityIcon(mCallingActivity); 809 } catch (NameNotFoundException e) { 810 Log.e(TAG, "Could not retrieve icon for calling activity", e); 811 } 812 return null; 813 } 814 815 /** 816 * Get the icon of the calling application as a Drawable if data 817 * about the calling package is available. 818 * 819 * <p><em>Note:</em> This data may have been provided voluntarily by the calling 820 * application. As such it should not be trusted for accuracy in the context of 821 * security or verification.</p> 822 * 823 * @return The calling application's icon or null if unknown 824 */ 825 public Drawable getCallingApplicationIcon() { 826 if (mCallingPackage == null) return null; 827 828 PackageManager pm = mActivity.getPackageManager(); 829 try { 830 return pm.getApplicationIcon(mCallingPackage); 831 } catch (NameNotFoundException e) { 832 Log.e(TAG, "Could not retrieve icon for calling application", e); 833 } 834 return null; 835 } 836 837 /** 838 * Get the human-readable label (title) of the calling application if 839 * data about the calling package is available. 840 * 841 * <p><em>Note:</em> This data may have been provided voluntarily by the calling 842 * application. As such it should not be trusted for accuracy in the context of 843 * security or verification.</p> 844 * 845 * @return The calling application's label or null if unknown 846 */ 847 public CharSequence getCallingApplicationLabel() { 848 if (mCallingPackage == null) return null; 849 850 PackageManager pm = mActivity.getPackageManager(); 851 try { 852 return pm.getApplicationLabel(pm.getApplicationInfo(mCallingPackage, 0)); 853 } catch (NameNotFoundException e) { 854 Log.e(TAG, "Could not retrieve label for calling application", e); 855 } 856 return null; 857 } 858 } 859} 860