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; |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 278 | 278 |
| 279 /** | 279 /** |
| 280 * Creates and shows a share intent picker dialog or starts a share intent d irectly with the | 280 * Creates and shows a share intent picker dialog or starts a share intent d irectly with the |
| 281 * activity that was most recently used to share based on shareDirectly valu e. | 281 * activity that was most recently used to share based on shareDirectly valu e. |
| 282 * | 282 * |
| 283 * This function will save |screenshot| under {app's root}/files/images/scre enshot (or | 283 * This function will save |screenshot| under {app's root}/files/images/scre enshot (or |
| 284 * /sdcard/DCIM/browser-images/screenshot if ADK is lower than JB MR2). | 284 * /sdcard/DCIM/browser-images/screenshot if ADK is lower than JB MR2). |
| 285 * Cleaning up doesn't happen automatically, and so an app should call clear SharedScreenshots() | 285 * Cleaning up doesn't happen automatically, and so an app should call clear SharedScreenshots() |
| 286 * explicitly when needed. | 286 * explicitly when needed. |
| 287 * | 287 * |
| 288 * @param shareDirectly Whether it should share directly with the activity t hat was most | 288 * @param params The container holding the share parameters. |
| 289 * recently used to share. | |
| 290 * @param saveLastUsed Whether to save the chosen activity for future direct sharing. | |
| 291 * @param activity Activity that is used to access package manager. | |
| 292 * @param title Title of the page to be shared. | |
| 293 * @param text Text to be shared. If both |text| and |url| are supplied, the y are concatenated | |
| 294 * with a space. | |
| 295 * @param url URL of the page to be shared. | |
| 296 * @param offlineUri URI to the offline MHTML file to be shared. | |
| 297 * @param screenshotUri Uri of the screenshot of the page to be shared. | |
| 298 * @param callback Optional callback to be called when user makes a choice. Will not be called | |
| 299 * if receiving a response when the user makes a choice is n ot supported (on | |
| 300 * older Android versions). | |
| 301 */ | 289 */ |
| 302 public static void share(boolean shareDirectly, boolean saveLastUsed, Activi ty activity, | 290 public static void share(ShareParams params) { |
| 303 String title, String text, String url, @Nullable Uri offlineUri, Uri screenshotUri, | 291 if (params.isShareDirectly()) { |
| 304 @Nullable TargetChosenCallback callback) { | 292 ComponentName component = getLastShareComponentName(); |
| 305 if (shareDirectly) { | 293 if (component == null) return; |
| 306 shareWithLastUsed(activity, title, text, url, offlineUri, screenshot Uri); | 294 makeIntentAndShare(params, component); |
| 307 } else if (TargetChosenReceiver.isSupported()) { | 295 } else if (TargetChosenReceiver.isSupported()) { |
| 308 makeIntentAndShare(saveLastUsed, activity, title, text, url, offline Uri, screenshotUri, | 296 makeIntentAndShare(params, null); |
| 309 null, callback); | |
| 310 } else { | 297 } else { |
| 311 showShareDialog( | 298 showShareDialog(params); |
| 312 saveLastUsed, activity, title, text, url, offlineUri, screen shotUri, callback); | |
| 313 } | 299 } |
| 314 } | 300 } |
| 315 | 301 |
| 316 /** | 302 /** |
| 317 * Trigger the share action for the given image data. | 303 * Trigger the share action for the given image data. |
| 318 * @param activity The activity used to trigger the share action. | 304 * @param activity The activity used to trigger the share action. |
| 319 * @param jpegImageData The image data to be shared in jpeg format. | 305 * @param jpegImageData The image data to be shared in jpeg format. |
| 320 * @param name When this is not null, it will share the image directly with the | 306 * @param name When this is not null, it will share the image directly with the |
| 321 * {@link ComponentName} | 307 * {@link ComponentName} |
| 322 */ | 308 */ |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 433 fileUri = ApiCompatibilityUtils.getUriForImageCaptureFile(sa vedFile); | 419 fileUri = ApiCompatibilityUtils.getUriForImageCaptureFile(sa vedFile); |
| 434 } | 420 } |
| 435 callback.onResult(fileUri); | 421 callback.onResult(fileUri); |
| 436 } | 422 } |
| 437 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); | 423 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
| 438 } | 424 } |
| 439 | 425 |
| 440 /** | 426 /** |
| 441 * Creates and shows a share intent picker dialog. | 427 * Creates and shows a share intent picker dialog. |
| 442 * | 428 * |
| 443 * @param saveLastUsed Whether to save the chosen activity for future direct sharing. | 429 * @param params The container holding the share parameters. |
| 444 * @param activity Activity that is used to access package manager. | |
| 445 * @param title Title of the page to be shared. | |
| 446 * @param text Text to be shared. If both |text| and |url| are supplied, the y are concatenated | |
| 447 * with a space. | |
| 448 * @param url URL of the page to be shared. | |
| 449 * @oaram offlineUri URI of the offline page to be shared. | |
| 450 * @param screenshotUri Uri of the screenshot of the page to be shared. | |
| 451 * @param callback Optional callback to be called when user makes a choice. Will not be called | |
| 452 * if receiving a response when the user makes a choice is n ot supported (on | |
| 453 * older Android versions). | |
| 454 */ | 430 */ |
| 455 private static void showShareDialog(final boolean saveLastUsed, final Activi ty activity, | 431 private static void showShareDialog(final ShareParams params) { |
| 456 final String title, final String text, final String url, final Uri o fflineUri, | 432 Activity activity = params.getActivity(); |
| 457 final Uri screenshotUri, @Nullable final TargetChosenCallback callba ck) { | 433 final TargetChosenCallback callback = params.getCallback(); |
| 458 Intent intent = getShareIntent(activity, title, text, url, null, null); | 434 Intent intent = getShareLinkAppCompatibilityIntent(); |
| 459 PackageManager manager = activity.getPackageManager(); | 435 PackageManager manager = activity.getPackageManager(); |
| 460 List<ResolveInfo> resolveInfoList = manager.queryIntentActivities(intent , 0); | 436 List<ResolveInfo> resolveInfoList = manager.queryIntentActivities(intent , 0); |
| 461 assert resolveInfoList.size() > 0; | 437 assert resolveInfoList.size() > 0; |
| 462 if (resolveInfoList.size() == 0) return; | 438 if (resolveInfoList.size() == 0) return; |
| 463 Collections.sort(resolveInfoList, new ResolveInfo.DisplayNameComparator( manager)); | 439 Collections.sort(resolveInfoList, new ResolveInfo.DisplayNameComparator( manager)); |
| 464 | 440 |
| 465 final ShareDialogAdapter adapter = | 441 final ShareDialogAdapter adapter = |
| 466 new ShareDialogAdapter(activity, manager, resolveInfoList); | 442 new ShareDialogAdapter(activity, manager, resolveInfoList); |
| 467 AlertDialog.Builder builder = new AlertDialog.Builder(activity, R.style. AlertDialogTheme); | 443 AlertDialog.Builder builder = new AlertDialog.Builder(activity, R.style. AlertDialogTheme); |
| 468 builder.setTitle(activity.getString(R.string.share_link_chooser_title)); | 444 builder.setTitle(activity.getString(R.string.share_link_chooser_title)); |
| 469 builder.setAdapter(adapter, null); | 445 builder.setAdapter(adapter, null); |
| 470 | 446 |
| 471 // Need a mutable object to record whether the callback has been fired. | 447 // Need a mutable object to record whether the callback has been fired. |
| 472 final boolean[] callbackCalled = new boolean[1]; | 448 final boolean[] callbackCalled = new boolean[1]; |
| 473 | 449 |
| 474 final AlertDialog dialog = builder.create(); | 450 final AlertDialog dialog = builder.create(); |
| 475 dialog.show(); | 451 dialog.show(); |
| 476 dialog.getListView().setOnItemClickListener(new OnItemClickListener() { | 452 dialog.getListView().setOnItemClickListener(new OnItemClickListener() { |
| 477 @Override | 453 @Override |
| 478 public void onItemClick(AdapterView<?> parent, View view, int positi on, long id) { | 454 public void onItemClick(AdapterView<?> parent, View view, int positi on, long id) { |
| 479 ResolveInfo info = adapter.getItem(position); | 455 ResolveInfo info = adapter.getItem(position); |
| 480 ActivityInfo ai = info.activityInfo; | 456 ActivityInfo ai = info.activityInfo; |
| 481 ComponentName component = | 457 ComponentName component = |
| 482 new ComponentName(ai.applicationInfo.packageName, ai.nam e); | 458 new ComponentName(ai.applicationInfo.packageName, ai.nam e); |
| 459 | |
| 483 if (callback != null && !callbackCalled[0]) { | 460 if (callback != null && !callbackCalled[0]) { |
| 484 callback.onTargetChosen(component); | 461 callback.onTargetChosen(component); |
| 485 callbackCalled[0] = true; | 462 callbackCalled[0] = true; |
| 486 } | 463 } |
| 487 if (saveLastUsed) setLastShareComponentName(component); | 464 if (params.isSaveLastUsed()) setLastShareComponentName(component ); |
| 488 makeIntentAndShare(false, activity, title, text, url, offlineUri , screenshotUri, | 465 makeIntentAndShare(params, component); |
| 489 component, null); | |
| 490 dialog.dismiss(); | 466 dialog.dismiss(); |
| 491 } | 467 } |
| 492 }); | 468 }); |
| 493 | 469 |
| 494 if (callback != null) { | 470 if (callback != null) { |
| 495 dialog.setOnDismissListener(new OnDismissListener() { | 471 dialog.setOnDismissListener(new OnDismissListener() { |
| 496 @Override | 472 @Override |
| 497 public void onDismiss(DialogInterface dialog) { | 473 public void onDismiss(DialogInterface dialog) { |
| 498 if (!callbackCalled[0]) { | 474 if (!callbackCalled[0]) { |
| 499 callback.onCancel(); | 475 callback.onCancel(); |
| 500 callbackCalled[0] = true; | 476 callbackCalled[0] = true; |
| 501 } | 477 } |
| 502 } | 478 } |
| 503 }); | 479 }); |
| 504 } | 480 } |
| 505 | 481 |
| 506 if (sFakeIntentReceiverForTesting != null) { | 482 if (sFakeIntentReceiverForTesting != null) { |
| 507 sFakeIntentReceiverForTesting.onCustomChooserShown(dialog); | 483 sFakeIntentReceiverForTesting.onCustomChooserShown(dialog); |
| 508 } | 484 } |
| 509 } | 485 } |
| 510 | 486 |
| 511 /** | 487 private static void makeIntentAndShare(ShareParams params, @Nullable Compone ntName component) { |
| 512 * Starts a share intent with the activity that was most recently used to sh are. | 488 Intent intent = getShareLinkIntent(params); |
| 513 * If there is no most recently used activity, it does nothing. | 489 intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT | Intent.FLAG_ACTIVI TY_PREVIOUS_IS_TOP); |
| 514 * @param activity Activity that is used to start the share intent. | 490 intent.setComponent(component); |
| 515 * @param title Title of the page to be shared. | 491 if (intent.getComponent() != null) { |
| 516 * @param text Text to be shared. If both |text| and |url| are supplied, the y are concatenated | |
| 517 * with a space. | |
| 518 * @param url URL of the page to be shared. | |
| 519 * @oaram offlineUri URI of the offline page to be shared. | |
| 520 * @param screenshotUri Uri of the screenshot of the page to be shared. | |
| 521 */ | |
| 522 private static void shareWithLastUsed(Activity activity, String title, Strin g text, String url, | |
| 523 Uri offlineUri, Uri screenshotUri) { | |
| 524 ComponentName component = getLastShareComponentName(); | |
| 525 if (component == null) return; | |
| 526 makeIntentAndShare( | |
| 527 false, activity, title, text, url, offlineUri, screenshotUri, co mponent, null); | |
| 528 } | |
| 529 | |
| 530 private static void shareIntent(boolean saveLastUsed, Activity activity, Int ent sharingIntent, | |
| 531 @Nullable TargetChosenCallback callback) { | |
| 532 if (sharingIntent.getComponent() != null) { | |
| 533 // If a component was specified, there should not also be a callback . | 492 // If a component was specified, there should not also be a callback . |
| 534 assert callback == null; | 493 assert params.getCallback() == null; |
| 535 fireIntent(activity, sharingIntent); | 494 fireIntent(params.getActivity(), intent); |
| 536 } else { | 495 } else { |
| 537 assert TargetChosenReceiver.isSupported(); | 496 assert TargetChosenReceiver.isSupported(); |
| 538 TargetChosenReceiver.sendChooserIntent(saveLastUsed, activity, shari ngIntent, callback); | 497 TargetChosenReceiver.sendChooserIntent( |
| 498 params.isSaveLastUsed(), params.getActivity(), intent, param s.getCallback()); | |
| 539 } | 499 } |
| 540 } | 500 } |
| 541 | 501 |
| 542 private static void makeIntentAndShare(final boolean saveLastUsed, final Act ivity activity, | |
| 543 final String title, final String text, final String url, final Uri o fflineUri, | |
| 544 final Uri screenshotUri, final ComponentName component, | |
| 545 @Nullable final TargetChosenCallback callback) { | |
| 546 Intent intent = getDirectShareIntentForComponent( | |
| 547 activity, title, text, url, offlineUri, screenshotUri, component ); | |
| 548 shareIntent(saveLastUsed, activity, intent, callback); | |
| 549 } | |
| 550 | |
| 551 /** | 502 /** |
| 552 * Set the icon and the title for the menu item used for direct share. | 503 * Set the icon and the title for the menu item used for direct share. |
| 553 * | 504 * |
| 554 * @param activity Activity that is used to access the package manager. | 505 * @param activity Activity that is used to access the package manager. |
| 555 * @param item The menu item that is used for direct share | 506 * @param item The menu item that is used for direct share |
| 556 */ | 507 */ |
| 557 public static void configureDirectShareMenuItem(Activity activity, MenuItem item) { | 508 public static void configureDirectShareMenuItem(Activity activity, MenuItem item) { |
| 558 Intent shareIntent = getShareIntent(activity, "", "", "", null, null); | 509 Intent shareIntent = getShareLinkAppCompatibilityIntent(); |
| 559 Pair<Drawable, CharSequence> directShare = getShareableIconAndName(activ ity, shareIntent); | 510 Pair<Drawable, CharSequence> directShare = getShareableIconAndName(activ ity, shareIntent); |
| 560 Drawable directShareIcon = directShare.first; | 511 Drawable directShareIcon = directShare.first; |
| 561 CharSequence directShareTitle = directShare.second; | 512 CharSequence directShareTitle = directShare.second; |
| 562 | 513 |
| 563 item.setIcon(directShareIcon); | 514 item.setIcon(directShareIcon); |
| 564 if (directShareTitle != null) { | 515 if (directShareTitle != null) { |
| 565 item.setTitle( | 516 item.setTitle( |
| 566 activity.getString(R.string.accessibility_menu_share_via, di rectShareTitle)); | 517 activity.getString(R.string.accessibility_menu_share_via, di rectShareTitle)); |
| 567 } | 518 } |
| 568 } | 519 } |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 642 @VisibleForTesting | 593 @VisibleForTesting |
| 643 public static void setLastShareComponentName(ComponentName component) { | 594 public static void setLastShareComponentName(ComponentName component) { |
| 644 SharedPreferences preferences = ContextUtils.getAppSharedPreferences(); | 595 SharedPreferences preferences = ContextUtils.getAppSharedPreferences(); |
| 645 SharedPreferences.Editor editor = preferences.edit(); | 596 SharedPreferences.Editor editor = preferences.edit(); |
| 646 editor.putString(PACKAGE_NAME_KEY, component.getPackageName()); | 597 editor.putString(PACKAGE_NAME_KEY, component.getPackageName()); |
| 647 editor.putString(CLASS_NAME_KEY, component.getClassName()); | 598 editor.putString(CLASS_NAME_KEY, component.getClassName()); |
| 648 editor.apply(); | 599 editor.apply(); |
| 649 } | 600 } |
| 650 | 601 |
| 651 @VisibleForTesting | 602 @VisibleForTesting |
| 652 public static Intent getShareIntent(Activity activity, String title, String text, String url, | 603 public static Intent getShareLinkIntent(ShareParams params) { |
| 653 Uri offlineUri, Uri screenshotUri) { | 604 String url = params.getUrl(); |
| 605 String text = params.getText(); | |
| 654 if (!TextUtils.isEmpty(url)) { | 606 if (!TextUtils.isEmpty(url)) { |
| 655 url = DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(url); | 607 url = DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(url); |
| 656 if (!TextUtils.isEmpty(text)) { | 608 if (!TextUtils.isEmpty(text)) { |
| 657 // Concatenate text and URL with a space. | 609 // Concatenate text and URL with a space. |
| 658 text = text + " " + url; | 610 text = text + " " + url; |
| 659 } else { | 611 } else { |
| 660 text = url; | 612 text = url; |
| 661 } | 613 } |
| 662 } | 614 } |
| 663 | 615 |
| 664 Intent intent = new Intent(Intent.ACTION_SEND); | 616 Intent intent = new Intent(Intent.ACTION_SEND); |
| 665 intent.addFlags(ApiCompatibilityUtils.getActivityNewDocumentFlag()); | 617 intent.addFlags(ApiCompatibilityUtils.getActivityNewDocumentFlag()); |
| 666 intent.putExtra(Intent.EXTRA_SUBJECT, title); | 618 intent.putExtra(Intent.EXTRA_SUBJECT, params.getTitle()); |
| 667 intent.putExtra(Intent.EXTRA_TEXT, text); | 619 intent.putExtra(Intent.EXTRA_TEXT, text); |
| 668 intent.putExtra(EXTRA_TASK_ID, activity.getTaskId()); | 620 intent.putExtra(EXTRA_TASK_ID, params.getActivity().getTaskId()); |
| 669 | 621 |
| 622 Uri screenshotUri = params.getScreenshotUri(); | |
| 670 if (screenshotUri != null) { | 623 if (screenshotUri != null) { |
| 671 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); | 624 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); |
| 672 } | |
| 673 if (screenshotUri != null) { | |
| 674 // To give read access to an Intent target, we need to put |screensh otUri| in clipData | 625 // To give read access to an Intent target, we need to put |screensh otUri| in clipData |
| 675 // because adding Intent.FLAG_GRANT_READ_URI_PERMISSION doesn't work for | 626 // because adding Intent.FLAG_GRANT_READ_URI_PERMISSION doesn't work for |
| 676 // EXTRA_SHARE_SCREENSHOT_AS_STREAM. | 627 // EXTRA_SHARE_SCREENSHOT_AS_STREAM. |
| 677 intent.setClipData(ClipData.newRawUri("", screenshotUri)); | 628 intent.setClipData(ClipData.newRawUri("", screenshotUri)); |
| 678 intent.putExtra(EXTRA_SHARE_SCREENSHOT_AS_STREAM, screenshotUri); | 629 intent.putExtra(EXTRA_SHARE_SCREENSHOT_AS_STREAM, screenshotUri); |
| 679 } | 630 } |
| 680 if (offlineUri == null) { | 631 if (params.getOfflineUri() == null) { |
| 681 intent.setType("text/plain"); | 632 intent.setType("text/plain"); |
| 682 } else { | 633 } else { |
| 683 intent.setType("multipart/related"); | 634 intent.setType("multipart/related"); |
| 684 intent.putExtra(Intent.EXTRA_STREAM, offlineUri); | 635 intent.putExtra(Intent.EXTRA_STREAM, params.getOfflineUri()); |
| 685 } | 636 } |
| 686 return intent; | 637 return intent; |
| 687 } | 638 } |
| 688 | 639 |
| 689 /** | 640 /** |
| 690 * Creates an Intent to share an image. | 641 * Creates an Intent to share an image. |
| 691 * @param imageUri The Uri of the image. | 642 * @param imageUri The Uri of the image. |
| 692 * @return The Intent used to share the image. | 643 * @return The Intent used to share the image. |
| 693 */ | 644 */ |
| 694 public static Intent getShareImageIntent(Uri imageUri) { | 645 public static Intent getShareImageIntent(Uri imageUri) { |
| 695 Intent intent = new Intent(Intent.ACTION_SEND); | 646 Intent intent = new Intent(Intent.ACTION_SEND); |
| 696 intent.addFlags(ApiCompatibilityUtils.getActivityNewDocumentFlag()); | 647 intent.addFlags(ApiCompatibilityUtils.getActivityNewDocumentFlag()); |
| 697 intent.setType("image/jpeg"); | 648 intent.setType("image/jpeg"); |
| 698 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); | 649 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); |
| 699 intent.putExtra(Intent.EXTRA_STREAM, imageUri); | 650 intent.putExtra(Intent.EXTRA_STREAM, imageUri); |
| 700 return intent; | 651 return intent; |
| 701 } | 652 } |
| 702 | 653 |
| 703 private static Intent getDirectShareIntentForComponent(Activity activity, St ring title, | 654 /** |
| 704 String text, String url, Uri offlineUri, Uri screenshotUri, Componen tName component) { | 655 * Convenient method to create an Intent to retrieve all the apps support sh aring text. |
|
Yusuf
2017/06/02 20:07:46
Convenience
ltian
2017/06/02 23:44:39
Done.
| |
| 705 Intent intent = getShareIntent(activity, title, text, url, offlineUri, s creenshotUri); | 656 */ |
| 706 intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT | 657 public static Intent getShareLinkAppCompatibilityIntent() { |
| 707 | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP); | 658 Intent intent = new Intent(Intent.ACTION_SEND); |
| 708 intent.setComponent(component); | 659 intent.addFlags(ApiCompatibilityUtils.getActivityNewDocumentFlag()); |
| 660 intent.putExtra(Intent.EXTRA_SUBJECT, ""); | |
| 661 intent.putExtra(Intent.EXTRA_TEXT, ""); | |
| 662 intent.setType("text/plain"); | |
| 709 return intent; | 663 return intent; |
| 710 } | 664 } |
| 711 | 665 |
| 712 /** | 666 /** |
| 713 * Gets the {@link ComponentName} of the app that was used to last share. | 667 * Gets the {@link ComponentName} of the app that was used to last share. |
| 714 */ | 668 */ |
| 715 @Nullable | 669 @Nullable |
| 716 public static ComponentName getLastShareComponentName() { | 670 public static ComponentName getLastShareComponentName() { |
| 717 SharedPreferences preferences = ContextUtils.getAppSharedPreferences(); | 671 SharedPreferences preferences = ContextUtils.getAppSharedPreferences(); |
| 718 String packageName = preferences.getString(PACKAGE_NAME_KEY, null); | 672 String packageName = preferences.getString(PACKAGE_NAME_KEY, null); |
| 719 String className = preferences.getString(CLASS_NAME_KEY, null); | 673 String className = preferences.getString(CLASS_NAME_KEY, null); |
| 720 if (packageName == null || className == null) return null; | 674 if (packageName == null || className == null) return null; |
| 721 return new ComponentName(packageName, className); | 675 return new ComponentName(packageName, className); |
| 722 } | 676 } |
| 723 } | 677 } |
| OLD | NEW |