Android Open Source - smartShareActionProvider-android Smart Share Action Provider






From Project

Back to project page smartShareActionProvider-android.

License

The source code is released under:

Apache License

If you think the Android project smartShareActionProvider-android listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (C) 2013 The Android Open Source Project
 *// w  w w .j av  a2  s .  co m
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package fr.rolandl.smartshareactionprovider;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.support.v4.view.ActionProvider;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.SubMenu;
import android.view.View;
import fr.rolandl.smartshareactionprovider.SmartActivityChooserModel.OnChooseActivityListener;

/**
 * This is a provider for a share action. It is responsible for creating views
 * that enable data sharing and also to show a sub menu with sharing activities
 * if the hosting item is placed on the overflow menu.
 * <p/>
 * <p class="note"><strong>Note:</strong> This class is included in the <a
 * href="{@docRoot}tools/extras/support-library.html">support library</a> for compatibility
 * with API level 7 and higher. If you're developing your app for API level 14 and higher
 * <em>only</em>, you should instead use the framework {@link android.widget.ShareActionProvider}
 * class.</p>
 * <p/>
 * <p>
 * Here is how to use the action provider with custom backing file in a {@link MenuItem}:
 * </p>
 * <pre><code>
 *  // In {@link android.app.Activity#onCreateOptionsMenu Activity.onCreateOptionsMenu()}
 *  public boolean onCreateOptionsMenu(Menu menu) {
 *      // Get the menu item.
 *      MenuItem menuItem = menu.findItem(R.id.my_menu_item);
 *      // Get the provider and hold onto it to set/change the share intent.
 *      mShareActionProvider = (SmartShareActionProvider) MenuItemCompat.getActionProvider(menuItem);
 *      // Set history different from the default before getting the action
 *      // view since a call to {@link android.support.v4.view.MenuItemCompat#getActionView(MenuItem) MenuItemCompat.getActionView()} calls
 *      // {@link ActionProvider#onCreateActionView()} which uses the backing file name. Omit this
 *      // line if using the default share history file is desired.
 *      mShareActionProvider.setShareHistoryFileName("custom_share_history.xml");
 *      . . .
 *  }
 * <p/>
 *  // Somewhere in the application.
 *  public void doShare(Intent shareIntent) {
 *      // When you want to share set the share intent.
 *      mShareActionProvider.setShareIntent(shareIntent);
 *  }
 * </code></pre>
 * <p>
 * <strong>Note:</strong> While the sample snippet demonstrates how to use this provider
 * in the context of a menu item, the use of the provider is not limited to menu items.
 * </p>
 * <p/>
 * <div class="special reference">
 * <h3>Developer Guides</h3>
 * <p/>
 * <p>For information about how to use {@link SmartShareActionProvider}, see the
 * <a href="{@docRoot}guide/topics/ui/actionbar.html#ActionProvider">Action Bar</a> API guide.</p>
 * </div>
 *
 * @see ActionProvider
 */
public class SmartShareActionProvider
    extends ActionProvider
{

  /**
   * Listener for the event of selecting a share target.
   */
  public static interface OnShareTargetSelectedListener
  {

    /**
     * Called when a share target has been selected. The client can
     * decide whether to perform some action before the sharing is
     * actually performed.
     * <p>
     * <strong>Note:</strong> Modifying the intent is not permitted and
     * any changes to the latter will be ignored.
     * </p>
     * <p>
     * <strong>Note:</strong> You should <strong>not</strong> handle the
     * intent here. This callback aims to notify the client that a
     * sharing is being performed, so the client can update the UI
     * if necessary.
     * </p>
     *
     * @param source The source of the notification.
     * @param intent The intent for launching the chosen share target.
     * @return The return result is ignored. Always return false for consistency.
     */
    public boolean onShareTargetSelected(SmartShareActionProvider source, Intent intent);

  }

  public static enum ShareIcon
  {
    White, Black;
  }

  /**
   * The default for the maximal number of activities shown in the sub-menu.
   */
  private static final int DEFAULT_INITIAL_ACTIVITY_COUNT = 4;

  /**
   * The the maximum number activities shown in the sub-menu.
   */
  private int mMaxShownActivityCount = DEFAULT_INITIAL_ACTIVITY_COUNT;

  /**
   * Listener for handling menu item clicks.
   */
  private final ShareMenuItemOnMenuItemClickListener mOnMenuItemClickListener = new ShareMenuItemOnMenuItemClickListener();

  /**
   * The default name for storing share history.
   */
  public static final String DEFAULT_SHARE_HISTORY_FILE_NAME = "share_history.xml";

  /**
   * Context for accessing resources.
   */
  private final Context mContext;

  private final int mDrawableResId;

  private final Drawable mDrawable;

  /**
   * The name of the file with share history data.
   */
  private String mShareHistoryFileName = DEFAULT_SHARE_HISTORY_FILE_NAME;

  private OnShareTargetSelectedListener mOnShareTargetSelectedListener;

  private OnChooseActivityListener mOnChooseActivityListener;

  /**
   * Creates a new instance.
   *
   * @param context Context for accessing resources.
   * @param icon    ShareIcon for stylizing the icon.
   */
  public SmartShareActionProvider(Context context, ShareIcon icon)
  {
    super(context);
    mContext = context;
    mDrawable = null;
    mDrawableResId = icon == ShareIcon.White ? R.drawable.ic_action_share : R.drawable.ic_action_share_black;
  }

  /**
   * Creates a new instance.
   *
   * @param context  Context for accessing resources.
   * @param drawable drawable for stylizing the icon.
   */
  public SmartShareActionProvider(Context context, Drawable drawable)
  {
    super(context);
    mContext = context;
    mDrawable = drawable;
    mDrawableResId = -1;
  }

  /**
   * Sets a listener to be notified when a share target has been selected.
   * The listener can optionally decide to handle the selection and
   * not rely on the default behavior which is to launch the activity.
   * <p>
   * <strong>Note:</strong> If you choose the backing share history file
   * you will still be notified in this callback.
   * </p>
   *
   * @param listener The listener.
   */
  public void setOnShareTargetSelectedListener(OnShareTargetSelectedListener listener)
  {
    mOnShareTargetSelectedListener = listener;
    setActivityChooserPolicyIfNeeded();
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public View onCreateActionView()
  {
    // Create the view and set its data model.
    SmartActivityChooserModel dataModel = SmartActivityChooserModel.get(mContext, mShareHistoryFileName);
    SmartActivityChooserView activityChooserView = new SmartActivityChooserView(mContext);
    activityChooserView.setActivityChooserModel(dataModel);

    // Lookup and set the expand action icon.
    // TypedValue outTypedValue = new TypedValue();
    //mContext.getTheme().resolveAttribute(R.attr.actionModeShareDrawable, outTypedValue, true);
    //Drawable drawable = TintManager.getDrawable(mContext, outTypedValue.resourceId);
    final Drawable drawable = mDrawable == null ? mContext.getResources().getDrawable(mDrawableResId) : mDrawable;
    activityChooserView.setExpandActivityOverflowButtonDrawable(drawable);
    activityChooserView.setProvider(this);

    // Set content description.
    activityChooserView.setDefaultActionButtonContentDescription(R.string.abc_shareactionprovider_share_with_application);
    activityChooserView.setExpandActivityOverflowButtonContentDescription(R.string.abc_shareactionprovider_share_with);

    return activityChooserView;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public boolean hasSubMenu()
  {
    return true;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public void onPrepareSubMenu(SubMenu subMenu)
  {
    // Clear since the order of items may change.
    subMenu.clear();

    SmartActivityChooserModel dataModel = SmartActivityChooserModel.get(mContext, mShareHistoryFileName);
    PackageManager packageManager = mContext.getPackageManager();

    final int expandedActivityCount = dataModel.getActivityCount();
    final int collapsedActivityCount = Math.min(expandedActivityCount, mMaxShownActivityCount);

    // Populate the sub-menu with a sub set of the activities.
    for (int i = 0; i < collapsedActivityCount; i++)
    {
      ResolveInfo activity = dataModel.getActivity(i);
      subMenu.add(0, i, i, activity.loadLabel(packageManager)).setIcon(activity.loadIcon(packageManager)).setOnMenuItemClickListener(mOnMenuItemClickListener);
    }

    if (collapsedActivityCount < expandedActivityCount)
    {
      // Add a sub-menu for showing all activities as a list item.
      SubMenu expandedSubMenu = subMenu.addSubMenu(Menu.NONE, collapsedActivityCount, collapsedActivityCount, mContext.getString(R.string.abc_activity_chooser_view_see_all));
      for (int i = 0; i < expandedActivityCount; i++)
      {
        ResolveInfo activity = dataModel.getActivity(i);
        expandedSubMenu.add(0, i, i, activity.loadLabel(packageManager)).setIcon(activity.loadIcon(packageManager)).setOnMenuItemClickListener(mOnMenuItemClickListener);
      }
    }
  }

  /**
   * Sets the file name of a file for persisting the share history which
   * history will be used for ordering share targets. This file will be used
   * for all view created by {@link #onCreateActionView()}. Defaults to
   * {@link #DEFAULT_SHARE_HISTORY_FILE_NAME}. Set to <code>null</code>
   * if share history should not be persisted between sessions.
   * <p/>
   * <strong>Note:</strong> The history file name can be set any time, however
   * only the action views created by {@link #onCreateActionView()} after setting
   * the file name will be backed by the provided file. Therefore, if you want to
   * use different history files for sharing specific types of content, every time
   * you change the history file {@link #setShareHistoryFileName(String)} you must
   * call {@link android.app.Activity#invalidateOptionsMenu()} to recreate the
   * action view. You should <strong>not</strong> call
   * {@link android.app.Activity#invalidateOptionsMenu()} from
   * {@link android.app.Activity#onCreateOptionsMenu(Menu)}."
   * <p/>
   * <code>
   * private void doShare(Intent intent) {
   * if (IMAGE.equals(intent.getMimeType())) {
   * mShareActionProvider.setHistoryFileName(SHARE_IMAGE_HISTORY_FILE_NAME);
   * } else if (TEXT.equals(intent.getMimeType())) {
   * mShareActionProvider.setHistoryFileName(SHARE_TEXT_HISTORY_FILE_NAME);
   * }
   * mShareActionProvider.setIntent(intent);
   * invalidateOptionsMenu();
   * }
   * <code>
   *
   * @param shareHistoryFile The share history file name.
   */
  public void setShareHistoryFileName(String shareHistoryFile)
  {
    mShareHistoryFileName = shareHistoryFile;
    setActivityChooserPolicyIfNeeded();
  }

  /**
   * Sets an intent with information about the share action. Here is a
   * sample for constructing a share intent:
   * <p>
   * <pre>
   * <code>
   *  Intent shareIntent = new Intent(Intent.ACTION_SEND);
   *  shareIntent.setType("image/*");
   *  Uri uri = Uri.fromFile(new File(getFilesDir(), "foo.jpg"));
   *  shareIntent.putExtra(Intent.EXTRA_STREAM, uri.toString());
   * </pre>
   * </code>
   * </p>
   *
   * @param shareIntent The share intent.
   * @see Intent#ACTION_SEND
   * @see Intent#ACTION_SEND_MULTIPLE
   */
  public void setShareIntent(Intent shareIntent)
  {
    SmartActivityChooserModel dataModel = SmartActivityChooserModel.get(mContext, mShareHistoryFileName);
    dataModel.setIntent(shareIntent);
  }

  /**
   * Reusable listener for handling share item clicks.
   */
  private class ShareMenuItemOnMenuItemClickListener
      implements OnMenuItemClickListener
  {

    @Override
    public boolean onMenuItemClick(MenuItem item)
    {
      SmartActivityChooserModel dataModel = SmartActivityChooserModel.get(mContext, mShareHistoryFileName);
      final int itemId = item.getItemId();
      Intent launchIntent = dataModel.chooseActivity(itemId);
      if (launchIntent != null)
      {
        launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
        mContext.startActivity(launchIntent);
      }
      return true;
    }
  }

  /**
   * Set the activity chooser policy of the model backed by the current
   * share history file if needed which is if there is a registered callback.
   */
  private void setActivityChooserPolicyIfNeeded()
  {
    if (mOnShareTargetSelectedListener == null)
    {
      return;
    }
    if (mOnChooseActivityListener == null)
    {
      mOnChooseActivityListener = new ShareActivityChooserModelPolicy();
    }
    SmartActivityChooserModel dataModel = SmartActivityChooserModel.get(mContext, mShareHistoryFileName);
    dataModel.setOnChooseActivityListener(mOnChooseActivityListener);
  }

  /**
   * Policy that delegates to the {@link OnShareTargetSelectedListener}, if such.
   */
  private class ShareActivityChooserModelPolicy
      implements OnChooseActivityListener
  {

    @Override
    public boolean onChooseActivity(SmartActivityChooserModel host, Intent intent)
    {
      if (mOnShareTargetSelectedListener != null)
      {
        mOnShareTargetSelectedListener.onShareTargetSelected(SmartShareActionProvider.this, intent);
      }
      return false;
    }
  }
}




Java Source Code List

fr.rolandl.sample.smartshareactionprovider.MainActivity.java
fr.rolandl.smartshareactionprovider.SmartActivityChooserModel.java
fr.rolandl.smartshareactionprovider.SmartActivityChooserView.java
fr.rolandl.smartshareactionprovider.SmartShareActionProvider.java