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
);