151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov/*
251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Copyright (C) 2011 The Android Open Source Project
351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov *
451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Licensed under the Apache License, Version 2.0 (the "License");
551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * you may not use this file except in compliance with the License.
651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * You may obtain a copy of the License at
751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov *
851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov *      http://www.apache.org/licenses/LICENSE-2.0
951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov *
1051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Unless required by applicable law or agreed to in writing, software
1151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * distributed under the License is distributed on an "AS IS" BASIS,
1251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * See the License for the specific language governing permissions and
1451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * limitations under the License.
1551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */
1651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
1751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovpackage android.widget;
1851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
1951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.content.Context;
2051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.content.Intent;
2176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganovimport android.content.pm.PackageManager;
2276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganovimport android.content.pm.ResolveInfo;
2351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.graphics.drawable.Drawable;
2451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.util.TypedValue;
2551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.view.ActionProvider;
2676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganovimport android.view.Menu;
2751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.view.MenuItem;
2876559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganovimport android.view.MenuItem.OnMenuItemClickListener;
29961dd11895ce72e59bca124ef5bea4e4c1183099Adam Powellimport android.view.SubMenu;
3051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.view.View;
318c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganovimport android.widget.ActivityChooserModel.OnChooseActivityListener;
3251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
3376559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganovimport com.android.internal.R;
3476559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov
3551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov/**
3651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * This is a provider for a share action. It is responsible for creating views
3776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov * that enable data sharing and also to show a sub menu with sharing activities
3876559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov * if the hosting item is placed on the overflow menu.
3951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * <p>
4051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Here is how to use the action provider with custom backing file in a {@link MenuItem}:
4151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * </p>
4251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * <pre>
4343d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick * // In Activity#onCreateOptionsMenu
4443d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick * public boolean onCreateOptionsMenu(Menu menu) {
4543d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick *     // Get the menu item.
4643d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick *     MenuItem menuItem = menu.findItem(R.id.my_menu_item);
4743d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick *     // Get the provider and hold onto it to set/change the share intent.
4843d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick *     mShareActionProvider = (ShareActionProvider) menuItem.getActionProvider();
4943d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick *     // Set history different from the default before getting the action
5043d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick *     // view since a call to {@link MenuItem#getActionView() MenuItem.getActionView()} calls
5143d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick *     // {@link ActionProvider#onCreateActionView()} which uses the backing file name. Omit this
5243d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick *     // line if using the default share history file is desired.
5343d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick *     mShareActionProvider.setShareHistoryFileName("custom_share_history.xml");
5443d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick *     . . .
5543d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick * }
5651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov *
5743d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick * // Somewhere in the application.
5843d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick * public void doShare(Intent shareIntent) {
5943d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick *     // When you want to share set the share intent.
6043d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick *     mShareActionProvider.setShareIntent(shareIntent);
6143d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick * }</pre>
6251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * <p>
6351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * <strong>Note:</strong> While the sample snippet demonstrates how to use this provider
6451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * in the context of a menu item, the use of the provider is not limited to menu items.
6551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * </p>
6651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov *
6751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * @see ActionProvider
6851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */
6951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovpublic class ShareActionProvider extends ActionProvider {
7051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
7151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
728c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov     * Listener for the event of selecting a share target.
738c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov     */
748c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov    public interface OnShareTargetSelectedListener {
758c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov
768c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov        /**
778c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov         * Called when a share target has been selected. The client can
78b33eacdb791e569ebb429b55d7ab098973e19764Svetoslav Ganov         * decide whether to perform some action before the sharing is
79b33eacdb791e569ebb429b55d7ab098973e19764Svetoslav Ganov         * actually performed.
808c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov         * <p>
818c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov         * <strong>Note:</strong> Modifying the intent is not permitted and
828c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov         *     any changes to the latter will be ignored.
838c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov         * </p>
84b33eacdb791e569ebb429b55d7ab098973e19764Svetoslav Ganov         * <p>
85b33eacdb791e569ebb429b55d7ab098973e19764Svetoslav Ganov         * <strong>Note:</strong> You should <strong>not</strong> handle the
86b33eacdb791e569ebb429b55d7ab098973e19764Svetoslav Ganov         *     intent here. This callback aims to notify the client that a
87b33eacdb791e569ebb429b55d7ab098973e19764Svetoslav Ganov         *     sharing is being performed, so the client can update the UI
88b33eacdb791e569ebb429b55d7ab098973e19764Svetoslav Ganov         *     if necessary.
89b33eacdb791e569ebb429b55d7ab098973e19764Svetoslav Ganov         * </p>
908c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov         *
918c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov         * @param source The source of the notification.
928c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov         * @param intent The intent for launching the chosen share target.
93b33eacdb791e569ebb429b55d7ab098973e19764Svetoslav Ganov         * @return The return result is ignored. Always return false for consistency.
948c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov         */
958c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov        public boolean onShareTargetSelected(ShareActionProvider source, Intent intent);
968c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov    }
978c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov
988c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov    /**
9976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov     * The default for the maximal number of activities shown in the sub-menu.
10076559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov     */
10176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov    private static final int DEFAULT_INITIAL_ACTIVITY_COUNT = 4;
10276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov
10376559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov    /**
10476559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov     * The the maximum number activities shown in the sub-menu.
10576559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov     */
10676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov    private int mMaxShownActivityCount = DEFAULT_INITIAL_ACTIVITY_COUNT;
10776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov
10876559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov    /**
10976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov     * Listener for handling menu item clicks.
11076559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov     */
11176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov    private final ShareMenuItemOnMenuItemClickListener mOnMenuItemClickListener =
11276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        new ShareMenuItemOnMenuItemClickListener();
11376559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov
11476559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov    /**
11551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * The default name for storing share history.
11651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
11751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    public static final String DEFAULT_SHARE_HISTORY_FILE_NAME = "share_history.xml";
11851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
11976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov    /**
12076559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov     * Context for accessing resources.
12176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov     */
12251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    private final Context mContext;
12376559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov
12476559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov    /**
12576559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov     * The name of the file with share history data.
12676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov     */
12751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    private String mShareHistoryFileName = DEFAULT_SHARE_HISTORY_FILE_NAME;
12851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
1298c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov    private OnShareTargetSelectedListener mOnShareTargetSelectedListener;
1308c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov
1318c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov    private OnChooseActivityListener mOnChooseActivityListener;
1328c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov
13351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
13451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * Creates a new instance.
13551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     *
13651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * @param context Context for accessing resources.
13751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
13851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    public ShareActionProvider(Context context) {
13951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        super(context);
14051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        mContext = context;
14151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
14251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
14351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
1448c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov     * Sets a listener to be notified when a share target has been selected.
1458c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov     * The listener can optionally decide to handle the selection and
1468c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov     * not rely on the default behavior which is to launch the activity.
1478c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov     * <p>
1488c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov     * <strong>Note:</strong> If you choose the backing share history file
1498c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov     *     you will still be notified in this callback.
1508c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov     * </p>
1518c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov     * @param listener The listener.
1528c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov     */
1538c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov    public void setOnShareTargetSelectedListener(OnShareTargetSelectedListener listener) {
1548c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov        mOnShareTargetSelectedListener = listener;
1558c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov        setActivityChooserPolicyIfNeeded();
1568c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov    }
1578c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov
1588c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov    /**
15951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * {@inheritDoc}
16051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
16151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    @Override
16251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    public View onCreateActionView() {
16376559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        // Create the view and set its data model.
16451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
16551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        ActivityChooserView activityChooserView = new ActivityChooserView(mContext);
16651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        activityChooserView.setActivityChooserModel(dataModel);
16776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov
16876559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        // Lookup and set the expand action icon.
16951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        TypedValue outTypedValue = new TypedValue();
17051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        mContext.getTheme().resolveAttribute(R.attr.actionModeShareDrawable, outTypedValue, true);
17151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        Drawable drawable = mContext.getResources().getDrawable(outTypedValue.resourceId);
17251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        activityChooserView.setExpandActivityOverflowButtonDrawable(drawable);
173823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell        activityChooserView.setProvider(this);
17476559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov
17570853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov        // Set content description.
17670853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov        activityChooserView.setDefaultActionButtonContentDescription(
17770853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov                R.string.shareactionprovider_share_with_application);
17870853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov        activityChooserView.setExpandActivityOverflowButtonContentDescription(
17970853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov                R.string.shareactionprovider_share_with);
18070853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov
18151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        return activityChooserView;
18251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
18351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
18476559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov    /**
18576559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov     * {@inheritDoc}
18676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov     */
18751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    @Override
188961dd11895ce72e59bca124ef5bea4e4c1183099Adam Powell    public boolean hasSubMenu() {
189961dd11895ce72e59bca124ef5bea4e4c1183099Adam Powell        return true;
190961dd11895ce72e59bca124ef5bea4e4c1183099Adam Powell    }
191961dd11895ce72e59bca124ef5bea4e4c1183099Adam Powell
19276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov    /**
19376559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov     * {@inheritDoc}
19476559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov     */
195961dd11895ce72e59bca124ef5bea4e4c1183099Adam Powell    @Override
196961dd11895ce72e59bca124ef5bea4e4c1183099Adam Powell    public void onPrepareSubMenu(SubMenu subMenu) {
19776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        // Clear since the order of items may change.
19876559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        subMenu.clear();
19976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov
20076559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
20176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        PackageManager packageManager = mContext.getPackageManager();
20276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov
20376559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        final int expandedActivityCount = dataModel.getActivityCount();
20476559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        final int collapsedActivityCount = Math.min(expandedActivityCount, mMaxShownActivityCount);
20576559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov
20676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        // Populate the sub-menu with a sub set of the activities.
20776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        for (int i = 0; i < collapsedActivityCount; i++) {
20876559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            ResolveInfo activity = dataModel.getActivity(i);
20976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            subMenu.add(0, i, i, activity.loadLabel(packageManager))
21076559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                .setIcon(activity.loadIcon(packageManager))
21176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                .setOnMenuItemClickListener(mOnMenuItemClickListener);
21276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        }
21376559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov
214414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov        if (collapsedActivityCount < expandedActivityCount) {
215414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov            // Add a sub-menu for showing all activities as a list item.
216414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov            SubMenu expandedSubMenu = subMenu.addSubMenu(Menu.NONE, collapsedActivityCount,
217414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov                    collapsedActivityCount,
218414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov                    mContext.getString(R.string.activity_chooser_view_see_all));
219414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov            for (int i = 0; i < expandedActivityCount; i++) {
220414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov                ResolveInfo activity = dataModel.getActivity(i);
221414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov                expandedSubMenu.add(0, i, i, activity.loadLabel(packageManager))
222414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov                    .setIcon(activity.loadIcon(packageManager))
223414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov                    .setOnMenuItemClickListener(mOnMenuItemClickListener);
224414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov            }
22576559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        }
22651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
22751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
22851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
22951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * Sets the file name of a file for persisting the share history which
23051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * history will be used for ordering share targets. This file will be used
23151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * for all view created by {@link #onCreateActionView()}. Defaults to
23251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * {@link #DEFAULT_SHARE_HISTORY_FILE_NAME}. Set to <code>null</code>
23351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * if share history should not be persisted between sessions.
23451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * <p>
23551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * <strong>Note:</strong> The history file name can be set any time, however
23651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * only the action views created by {@link #onCreateActionView()} after setting
237775bcac6bcdd04b6bffd23b5de0da4588a749337Svetoslav Ganov     * the file name will be backed by the provided file. Therefore, if you want to
238775bcac6bcdd04b6bffd23b5de0da4588a749337Svetoslav Ganov     * use different history files for sharing specific types of content, every time
239775bcac6bcdd04b6bffd23b5de0da4588a749337Svetoslav Ganov     * you change the history file {@link #setShareHistoryFileName(String)} you must
240775bcac6bcdd04b6bffd23b5de0da4588a749337Svetoslav Ganov     * call {@link android.app.Activity#invalidateOptionsMenu()} to recreate the
241775bcac6bcdd04b6bffd23b5de0da4588a749337Svetoslav Ganov     * action view. You should <strong>not</strong> call
242775bcac6bcdd04b6bffd23b5de0da4588a749337Svetoslav Ganov     * {@link android.app.Activity#invalidateOptionsMenu()} from
24343d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick     * {@link android.app.Activity#onCreateOptionsMenu(Menu)}.
24443d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick     * </p>
24543d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick     * <pre>
246775bcac6bcdd04b6bffd23b5de0da4588a749337Svetoslav Ganov     * private void doShare(Intent intent) {
247775bcac6bcdd04b6bffd23b5de0da4588a749337Svetoslav Ganov     *     if (IMAGE.equals(intent.getMimeType())) {
248775bcac6bcdd04b6bffd23b5de0da4588a749337Svetoslav Ganov     *         mShareActionProvider.setHistoryFileName(SHARE_IMAGE_HISTORY_FILE_NAME);
249775bcac6bcdd04b6bffd23b5de0da4588a749337Svetoslav Ganov     *     } else if (TEXT.equals(intent.getMimeType())) {
250775bcac6bcdd04b6bffd23b5de0da4588a749337Svetoslav Ganov     *         mShareActionProvider.setHistoryFileName(SHARE_TEXT_HISTORY_FILE_NAME);
251775bcac6bcdd04b6bffd23b5de0da4588a749337Svetoslav Ganov     *     }
252775bcac6bcdd04b6bffd23b5de0da4588a749337Svetoslav Ganov     *     mShareActionProvider.setIntent(intent);
253775bcac6bcdd04b6bffd23b5de0da4588a749337Svetoslav Ganov     *     invalidateOptionsMenu();
25443d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick     * }</pre>
25551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * @param shareHistoryFile The share history file name.
25651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
25751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    public void setShareHistoryFileName(String shareHistoryFile) {
25851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        mShareHistoryFileName = shareHistoryFile;
2598c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov        setActivityChooserPolicyIfNeeded();
26051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
26151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
26251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
26351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * Sets an intent with information about the share action. Here is a
26451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * sample for constructing a share intent:
26551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * <pre>
26643d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick     * Intent shareIntent = new Intent(Intent.ACTION_SEND);
26743d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick     * shareIntent.setType("image/*");
26843d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick     * Uri uri = Uri.fromFile(new File(getFilesDir(), "foo.jpg"));
26943d5abbf0343a1761814ce1743e40a6688a72e4ckmccormick     * shareIntent.putExtra(Intent.EXTRA_STREAM, uri.toString());</pre>
27051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     *
27151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * @param shareIntent The share intent.
27251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     *
27351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * @see Intent#ACTION_SEND
27451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * @see Intent#ACTION_SEND_MULTIPLE
27551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
27676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov    public void setShareIntent(Intent shareIntent) {
27776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        ActivityChooserModel dataModel = ActivityChooserModel.get(mContext,
27876559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            mShareHistoryFileName);
27976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        dataModel.setIntent(shareIntent);
28076559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov    }
28176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov
28276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov    /**
28376559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov     * Reusable listener for handling share item clicks.
28476559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov     */
28576559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov    private class ShareMenuItemOnMenuItemClickListener implements OnMenuItemClickListener {
28676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        @Override
28776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        public boolean onMenuItemClick(MenuItem item) {
28876559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            ActivityChooserModel dataModel = ActivityChooserModel.get(mContext,
28976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                    mShareHistoryFileName);
29076559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            final int itemId = item.getItemId();
29176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            Intent launchIntent = dataModel.chooseActivity(itemId);
2928c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov            if (launchIntent != null) {
293314419ccb9daa215c5148f59e5b60c696ef51385Adam Powell                launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
2948c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov                mContext.startActivity(launchIntent);
2958c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov            }
29676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            return true;
29751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
29851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
2998c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov
3008c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov    /**
3018c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov     * Set the activity chooser policy of the model backed by the current
3028c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov     * share history file if needed which is if there is a registered callback.
3038c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov     */
3048c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov    private void setActivityChooserPolicyIfNeeded() {
3058c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov        if (mOnShareTargetSelectedListener == null) {
3068c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov            return;
3078c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov        }
3088c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov        if (mOnChooseActivityListener == null) {
3098c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov            mOnChooseActivityListener = new ShareAcitivityChooserModelPolicy();
3108c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov        }
3118c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov        ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
3128c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov        dataModel.setOnChooseActivityListener(mOnChooseActivityListener);
3138c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov    }
3148c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov
3158c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov    /**
3168c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov     * Policy that delegates to the {@link OnShareTargetSelectedListener}, if such.
3178c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov     */
3188c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov    private class ShareAcitivityChooserModelPolicy implements OnChooseActivityListener {
3198c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov        @Override
3208c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov        public boolean onChooseActivity(ActivityChooserModel host, Intent intent) {
3218c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov            if (mOnShareTargetSelectedListener != null) {
322b33eacdb791e569ebb429b55d7ab098973e19764Svetoslav Ganov                mOnShareTargetSelectedListener.onShareTargetSelected(
3238c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov                        ShareActionProvider.this, intent);
3248c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov            }
3258c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov            return false;
3268c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov        }
3278c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov    }
32851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov}
329