2 * Copyright (C) 2011 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.actionbarsherlock.widget;
19 import android.content.Context;
20 import android.content.Intent;
21 import android.content.pm.PackageManager;
22 import android.content.pm.ResolveInfo;
23 import android.graphics.drawable.Drawable;
24 import android.util.TypedValue;
25 import android.view.View;
27 import com.actionbarsherlock.R;
28 import com.actionbarsherlock.view.ActionProvider;
29 import com.actionbarsherlock.view.Menu;
30 import com.actionbarsherlock.view.MenuItem;
31 import com.actionbarsherlock.view.MenuItem.OnMenuItemClickListener;
32 import com.actionbarsherlock.view.SubMenu;
33 import com.actionbarsherlock.widget.ActivityChooserModel.OnChooseActivityListener;
36 * This is a provider for a share action. It is responsible for creating views
37 * that enable data sharing and also to show a sub menu with sharing activities
38 * if the hosting item is placed on the overflow menu.
40 * Here is how to use the action provider with custom backing file in a {@link MenuItem}:
45 * // In Activity#onCreateOptionsMenu
46 * public boolean onCreateOptionsMenu(Menu menu) {
47 * // Get the menu item.
48 * MenuItem menuItem = menu.findItem(R.id.my_menu_item);
49 * // Get the provider and hold onto it to set/change the share intent.
50 * mShareActionProvider = (ShareActionProvider) menuItem.getActionProvider();
51 * // Set history different from the default before getting the action
52 * // view since a call to {@link MenuItem#getActionView() MenuItem.getActionView()} calls
53 * // {@link ActionProvider#onCreateActionView()} which uses the backing file name. Omit this
54 * // line if using the default share history file is desired.
55 * mShareActionProvider.setShareHistoryFileName("custom_share_history.xml");
59 * // Somewhere in the application.
60 * public void doShare(Intent shareIntent) {
61 * // When you want to share set the share intent.
62 * mShareActionProvider.setShareIntent(shareIntent);
68 * <strong>Note:</strong> While the sample snippet demonstrates how to use this provider
69 * in the context of a menu item, the use of the provider is not limited to menu items.
74 public class ShareActionProvider extends ActionProvider {
77 * Listener for the event of selecting a share target.
79 public interface OnShareTargetSelectedListener {
82 * Called when a share target has been selected. The client can
83 * decide whether to handle the intent or rely on the default
84 * behavior which is launching it.
86 * <strong>Note:</strong> Modifying the intent is not permitted and
87 * any changes to the latter will be ignored.
90 * @param source The source of the notification.
91 * @param intent The intent for launching the chosen share target.
92 * @return Whether the client has handled the intent.
94 public boolean onShareTargetSelected(ShareActionProvider source, Intent intent);
98 * The default for the maximal number of activities shown in the sub-menu.
100 private static final int DEFAULT_INITIAL_ACTIVITY_COUNT = 4;
103 * The the maximum number activities shown in the sub-menu.
105 private int mMaxShownActivityCount = DEFAULT_INITIAL_ACTIVITY_COUNT;
108 * Listener for handling menu item clicks.
110 private final ShareMenuItemOnMenuItemClickListener mOnMenuItemClickListener =
111 new ShareMenuItemOnMenuItemClickListener();
114 * The default name for storing share history.
116 public static final String DEFAULT_SHARE_HISTORY_FILE_NAME = "share_history.xml";
119 * Context for accessing resources.
121 private final Context mContext;
124 * The name of the file with share history data.
126 private String mShareHistoryFileName = DEFAULT_SHARE_HISTORY_FILE_NAME;
128 private OnShareTargetSelectedListener mOnShareTargetSelectedListener;
130 private OnChooseActivityListener mOnChooseActivityListener;
133 * Creates a new instance.
135 * @param context Context for accessing resources.
137 public ShareActionProvider(Context context) {
143 * Sets a listener to be notified when a share target has been selected.
144 * The listener can optionally decide to handle the selection and
145 * not rely on the default behavior which is to launch the activity.
147 * <strong>Note:</strong> If you choose the backing share history file
148 * you will still be notified in this callback.
150 * @param listener The listener.
152 public void setOnShareTargetSelectedListener(OnShareTargetSelectedListener listener) {
153 mOnShareTargetSelectedListener = listener;
154 setActivityChooserPolicyIfNeeded();
161 public View onCreateActionView() {
162 // Create the view and set its data model.
163 ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
164 ActivityChooserView activityChooserView = new ActivityChooserView(mContext);
165 activityChooserView.setActivityChooserModel(dataModel);
167 // Lookup and set the expand action icon.
168 TypedValue outTypedValue = new TypedValue();
169 mContext.getTheme().resolveAttribute(R.attr.actionModeShareDrawable, outTypedValue, true);
170 Drawable drawable = mContext.getResources().getDrawable(outTypedValue.resourceId);
171 activityChooserView.setExpandActivityOverflowButtonDrawable(drawable);
172 activityChooserView.setProvider(this);
174 // Set content description.
175 activityChooserView.setDefaultActionButtonContentDescription(
176 R.string.abs__shareactionprovider_share_with_application);
177 activityChooserView.setExpandActivityOverflowButtonContentDescription(
178 R.string.abs__shareactionprovider_share_with);
180 return activityChooserView;
187 public boolean hasSubMenu() {
195 public void onPrepareSubMenu(SubMenu subMenu) {
196 // Clear since the order of items may change.
199 ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
200 PackageManager packageManager = mContext.getPackageManager();
202 final int expandedActivityCount = dataModel.getActivityCount();
203 final int collapsedActivityCount = Math.min(expandedActivityCount, mMaxShownActivityCount);
205 // Populate the sub-menu with a sub set of the activities.
206 for (int i = 0; i < collapsedActivityCount; i++) {
207 ResolveInfo activity = dataModel.getActivity(i);
208 subMenu.add(0, i, i, activity.loadLabel(packageManager))
209 .setIcon(activity.loadIcon(packageManager))
210 .setOnMenuItemClickListener(mOnMenuItemClickListener);
213 if (collapsedActivityCount < expandedActivityCount) {
214 // Add a sub-menu for showing all activities as a list item.
215 SubMenu expandedSubMenu = subMenu.addSubMenu(Menu.NONE, collapsedActivityCount,
216 collapsedActivityCount,
217 mContext.getString(R.string.abs__activity_chooser_view_see_all));
218 for (int i = 0; i < expandedActivityCount; i++) {
219 ResolveInfo activity = dataModel.getActivity(i);
220 expandedSubMenu.add(0, i, i, activity.loadLabel(packageManager))
221 .setIcon(activity.loadIcon(packageManager))
222 .setOnMenuItemClickListener(mOnMenuItemClickListener);
228 * Sets the file name of a file for persisting the share history which
229 * history will be used for ordering share targets. This file will be used
230 * for all view created by {@link #onCreateActionView()}. Defaults to
231 * {@link #DEFAULT_SHARE_HISTORY_FILE_NAME}. Set to <code>null</code>
232 * if share history should not be persisted between sessions.
234 * <strong>Note:</strong> The history file name can be set any time, however
235 * only the action views created by {@link #onCreateActionView()} after setting
236 * the file name will be backed by the provided file.
239 * @param shareHistoryFile The share history file name.
241 public void setShareHistoryFileName(String shareHistoryFile) {
242 mShareHistoryFileName = shareHistoryFile;
243 setActivityChooserPolicyIfNeeded();
247 * Sets an intent with information about the share action. Here is a
248 * sample for constructing a share intent:
252 * Intent shareIntent = new Intent(Intent.ACTION_SEND);
253 * shareIntent.setType("image/*");
254 * Uri uri = Uri.fromFile(new File(getFilesDir(), "foo.jpg"));
255 * shareIntent.putExtra(Intent.EXTRA_STREAM, uri.toString());
260 * @param shareIntent The share intent.
262 * @see Intent#ACTION_SEND
263 * @see Intent#ACTION_SEND_MULTIPLE
265 public void setShareIntent(Intent shareIntent) {
266 ActivityChooserModel dataModel = ActivityChooserModel.get(mContext,
267 mShareHistoryFileName);
268 dataModel.setIntent(shareIntent);
272 * Reusable listener for handling share item clicks.
274 private class ShareMenuItemOnMenuItemClickListener implements OnMenuItemClickListener {
276 public boolean onMenuItemClick(MenuItem item) {
277 ActivityChooserModel dataModel = ActivityChooserModel.get(mContext,
278 mShareHistoryFileName);
279 final int itemId = item.getItemId();
280 Intent launchIntent = dataModel.chooseActivity(itemId);
281 if (launchIntent != null) {
282 mContext.startActivity(launchIntent);
289 * Set the activity chooser policy of the model backed by the current
290 * share history file if needed which is if there is a registered callback.
292 private void setActivityChooserPolicyIfNeeded() {
293 if (mOnShareTargetSelectedListener == null) {
296 if (mOnChooseActivityListener == null) {
297 mOnChooseActivityListener = new ShareAcitivityChooserModelPolicy();
299 ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
300 dataModel.setOnChooseActivityListener(mOnChooseActivityListener);
304 * Policy that delegates to the {@link OnShareTargetSelectedListener}, if such.
306 private class ShareAcitivityChooserModelPolicy implements OnChooseActivityListener {
308 public boolean onChooseActivity(ActivityChooserModel host, Intent intent) {
309 if (mOnShareTargetSelectedListener != null) {
310 return mOnShareTargetSelectedListener.onShareTargetSelected(
311 ShareActionProvider.this, intent);