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
3 // found in the LICENSE file.
5 package org.chromium.chrome.browser.share;
7 import android.app.Activity;
8 import android.app.AlertDialog;
9 import android.content.ComponentName;
10 import android.content.Context;
11 import android.content.Intent;
12 import android.content.SharedPreferences;
13 import android.content.pm.ActivityInfo;
14 import android.content.pm.ApplicationInfo;
15 import android.content.pm.PackageManager;
16 import android.content.pm.PackageManager.NameNotFoundException;
17 import android.content.pm.ResolveInfo;
18 import android.graphics.Bitmap;
19 import android.graphics.drawable.Drawable;
20 import android.preference.PreferenceManager;
21 import android.view.MenuItem;
22 import android.view.View;
23 import android.widget.AdapterView;
24 import android.widget.AdapterView.OnItemClickListener;
26 import org.chromium.chrome.R;
28 import java.util.Collections;
29 import java.util.List;
32 * A helper class that helps to start an intent to share titles and URLs.
34 public class ShareHelper {
36 private static final String PACKAGE_NAME_KEY = "last_shared_package_name";
37 private static final String CLASS_NAME_KEY = "last_shared_class_name";
40 * Intent extra for sharing screenshots via the Share intent.
42 * Copied from {@link android.provider.Browser} as it is marked as {@literal @hide}.
44 private static final String EXTRA_SHARE_SCREENSHOT = "share_screenshot";
46 private ShareHelper() {}
49 * Creates and shows a share intent picker dialog or starts a share intent directly with the
50 * activity that was most recently used to share based on shareDirectly value.
52 * @param shareDirectly Whether it should share directly with the activity that was most
53 * recently used to share.
54 * @param activity Activity that is used to access package manager.
55 * @param title Title of the page to be shared.
56 * @param url URL of the page to be shared.
57 * @param screenshot Screenshot of the page to be shared.
59 public static void share(boolean shareDirectly, Activity activity, String title, String url,
60 Bitmap screenshot, int extraIntentFlags) {
62 shareWithLastUsed(activity, title, url, screenshot, extraIntentFlags);
64 showShareDialog(activity, title, url, screenshot, extraIntentFlags);
69 * Creates and shows a share intent picker dialog.
71 * @param activity Activity that is used to access package manager.
72 * @param title Title of the page to be shared.
73 * @param url URL of the page to be shared.
74 * @param screenshot Screenshot of the page to be shared.
75 * @param extraIntentFlags Additional flags that should be added to the share intent.
77 private static void showShareDialog(final Activity activity, final String title,
78 final String url, final Bitmap screenshot, final int extraIntentFlags) {
79 Intent intent = getShareIntent(title, url, screenshot, extraIntentFlags);
80 PackageManager manager = activity.getPackageManager();
81 List<ResolveInfo> resolveInfoList = manager.queryIntentActivities(intent, 0);
82 assert resolveInfoList.size() > 0;
83 if (resolveInfoList.size() == 0) return;
84 Collections.sort(resolveInfoList, new ResolveInfo.DisplayNameComparator(manager));
86 final ShareDialogAdapter adapter =
87 new ShareDialogAdapter(activity, manager, resolveInfoList);
88 AlertDialog.Builder builder = new AlertDialog.Builder(activity);
89 builder.setTitle(activity.getString(R.string.share_link_chooser_title));
90 builder.setAdapter(adapter, null);
92 final AlertDialog dialog = builder.create();
94 dialog.getListView().setOnItemClickListener(new OnItemClickListener() {
96 public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
97 ResolveInfo info = adapter.getItem(position);
98 ActivityInfo ai = info.activityInfo;
99 ComponentName component =
100 new ComponentName(ai.applicationInfo.packageName, ai.name);
101 setLastShareComponentName(activity, component);
102 Intent intent = getDirectShareIntentForComponent(title, url, screenshot, component,
104 activity.startActivity(intent);
111 * Starts a share intent with the activity that was most recently used to share.
112 * If there is no most recently used activity, it does nothing.
113 * @param activity Activity that is used to start the share intent.
114 * @param title Title of the page to be shared.
115 * @param url URL of the page to be shared.
116 * @param screenshot Screenshot of the page to be shared.
117 * @param extraIntentFlags Additional flags that should be added to the share intent.
119 private static void shareWithLastUsed(
120 Activity activity, String title, String url, Bitmap screenshot, int extraIntentFlags) {
121 ComponentName component = getLastShareComponentName(activity);
122 if (component == null) return;
123 Intent intent = getDirectShareIntentForComponent(
124 title, url, screenshot, component, extraIntentFlags);
125 activity.startActivity(intent);
129 * Set the icon and the title for the menu item used for direct share.
131 * @param activity Activity that is used to access the package manager.
132 * @param item The menu item that is used for direct share
134 public static void configureDirectShareMenuItem(Activity activity, MenuItem item) {
135 Drawable directShareIcon = null;
136 CharSequence directShareTitle = null;
138 ComponentName component = getLastShareComponentName(activity);
139 if (component != null) {
141 directShareIcon = activity.getPackageManager().getActivityIcon(component);
142 ApplicationInfo ai = activity.getPackageManager().getApplicationInfo(
143 component.getPackageName(), 0);
144 directShareTitle = activity.getPackageManager().getApplicationLabel(ai);
145 } catch (NameNotFoundException exception) {
146 // Use the default null values.
150 item.setIcon(directShareIcon);
151 if (directShareTitle != null) {
152 item.setTitle(activity.getString(R.string.accessibility_menu_share_via,
157 private static Intent getShareIntent(String title, String url, Bitmap screenshot,
158 int extraIntentFlags) {
159 Intent intent = new Intent(Intent.ACTION_SEND);
160 intent.addFlags(extraIntentFlags);
161 intent.setType("text/plain");
162 intent.putExtra(Intent.EXTRA_SUBJECT, title);
163 intent.putExtra(Intent.EXTRA_TEXT, url);
164 if (screenshot != null) intent.putExtra(EXTRA_SHARE_SCREENSHOT, screenshot);
168 private static Intent getDirectShareIntentForComponent(String title, String url,
169 Bitmap screenshot, ComponentName component, int extraIntentFlags) {
170 Intent intent = getShareIntent(title, url, screenshot, extraIntentFlags);
171 intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT
172 | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
173 intent.setComponent(component);
177 private static ComponentName getLastShareComponentName(Context context) {
178 SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
179 String packageName = preferences.getString(PACKAGE_NAME_KEY, null);
180 String className = preferences.getString(CLASS_NAME_KEY, null);
181 if (packageName == null || className == null) return null;
182 return new ComponentName(packageName, className);
185 private static void setLastShareComponentName(Context context, ComponentName component) {
186 SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
187 SharedPreferences.Editor editor = preferences.edit();
188 editor.putString(PACKAGE_NAME_KEY, component.getPackageName());
189 editor.putString(CLASS_NAME_KEY, component.getClassName());