Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8c6c79f0 authored by Svetoslav Ganov's avatar Svetoslav Ganov
Browse files

Adding a callback to ShareActionProvider + make ActivityChooserView popup hide on action bar hide.

1. Added a callback to ShareActionProvider allowing clients to be notified
   when an activity is chosed given them a change to say update their UI and
   also decide whether to handle the activity launch themselves.

2. The popup of the ActivityChooserView was not hiding on hiding the action bar.

bug:5094963
bug:5095004

Change-Id: I6c8e8cc1f22d07e707e2218eb108f9101417b23b
parent 7abaecc3
Loading
Loading
Loading
Loading
+5 −0
Original line number Original line Diff line number Diff line
@@ -26480,11 +26480,16 @@ package android.widget {
  public class ShareActionProvider extends android.view.ActionProvider {
  public class ShareActionProvider extends android.view.ActionProvider {
    ctor public ShareActionProvider(android.content.Context);
    ctor public ShareActionProvider(android.content.Context);
    method public android.view.View onCreateActionView();
    method public android.view.View onCreateActionView();
    method public void setOnShareTargetSelectedListener(android.widget.ShareActionProvider.OnShareTargetSelectedListener);
    method public void setShareHistoryFileName(java.lang.String);
    method public void setShareHistoryFileName(java.lang.String);
    method public void setShareIntent(android.content.Intent);
    method public void setShareIntent(android.content.Intent);
    field public static final java.lang.String DEFAULT_SHARE_HISTORY_FILE_NAME = "share_history.xml";
    field public static final java.lang.String DEFAULT_SHARE_HISTORY_FILE_NAME = "share_history.xml";
  }
  }
  public static abstract interface ShareActionProvider.OnShareTargetSelectedListener {
    method public abstract boolean onShareTargetSelected(android.widget.ShareActionProvider, android.content.Intent);
  }
  public class SimpleAdapter extends android.widget.BaseAdapter implements android.widget.Filterable {
  public class SimpleAdapter extends android.widget.BaseAdapter implements android.widget.Filterable {
    ctor public SimpleAdapter(android.content.Context, java.util.List<? extends java.util.Map<java.lang.String, ?>>, int, java.lang.String[], int[]);
    ctor public SimpleAdapter(android.content.Context, java.util.List<? extends java.util.Map<java.lang.String, ?>>, int, java.lang.String[], int[]);
    method public int getCount();
    method public int getCount();
+55 −4
Original line number Original line Diff line number Diff line
@@ -130,6 +130,30 @@ public class ActivityChooserModel extends DataSetObservable {
                List<HistoricalRecord> historicalRecords);
                List<HistoricalRecord> historicalRecords);
    }
    }


    /**
     * Listener for choosing an activity.
     */
    public interface OnChooseActivityListener {

        /**
         * Called when an activity has been chosen. The client can decide whether
         * an activity can be chosen and if so the caller of
         * {@link ActivityChooserModel#chooseActivity(int)} will receive and {@link Intent}
         * for launching it.
         * <p>
         * <strong>Note:</strong> Modifying the intent is not permitted and
         *     any changes to the latter will be ignored.
         * </p>
         *
         * @param host The listener's host model.
         * @param intent The intent for launching the chosen activity.
         * @return Whether the intent is handled and should not be delivered to clients.
         *
         * @see ActivityChooserModel#chooseActivity(int)
         */
        public boolean onChooseActivity(ActivityChooserModel host, Intent intent);
    }

    /**
    /**
     * Flag for selecting debug mode.
     * Flag for selecting debug mode.
     */
     */
@@ -286,6 +310,11 @@ public class ActivityChooserModel extends DataSetObservable {
     */
     */
    private final Handler mHandler = new Handler();
    private final Handler mHandler = new Handler();


    /**
     * Policy for controlling how the model handles chosen activities.
     */
    private OnChooseActivityListener mActivityChoserModelPolicy;

    /**
    /**
     * Gets the data model backed by the contents of the provided file with historical data.
     * Gets the data model backed by the contents of the provided file with historical data.
     * Note that only one data model is backed by a given file, thus multiple calls with
     * Note that only one data model is backed by a given file, thus multiple calls with
@@ -426,9 +455,11 @@ public class ActivityChooserModel extends DataSetObservable {
     * the client solely to let additional customization before the start.
     * the client solely to let additional customization before the start.
     * </p>
     * </p>
     *
     *
     * @return Whether adding succeeded.
     * @return An {@link Intent} for launching the activity or null if the
     *         policy has consumed the intent.
     *
     *
     * @see HistoricalRecord
     * @see HistoricalRecord
     * @see OnChooseActivityListener
     */
     */
    public Intent chooseActivity(int index) {
    public Intent chooseActivity(int index) {
        ActivityResolveInfo chosenActivity = mActivites.get(index);
        ActivityResolveInfo chosenActivity = mActivites.get(index);
@@ -436,16 +467,36 @@ public class ActivityChooserModel extends DataSetObservable {
        ComponentName chosenName = new ComponentName(
        ComponentName chosenName = new ComponentName(
                chosenActivity.resolveInfo.activityInfo.packageName,
                chosenActivity.resolveInfo.activityInfo.packageName,
                chosenActivity.resolveInfo.activityInfo.name);
                chosenActivity.resolveInfo.activityInfo.name);
        HistoricalRecord historicalRecord = new HistoricalRecord(chosenName,
                System.currentTimeMillis(), DEFAULT_HISTORICAL_RECORD_WEIGHT);
        addHisoricalRecord(historicalRecord);


        Intent choiceIntent = new Intent(mIntent);
        Intent choiceIntent = new Intent(mIntent);
        choiceIntent.setComponent(chosenName);
        choiceIntent.setComponent(chosenName);


        if (mActivityChoserModelPolicy != null) {
            // Do not allow the policy to change the intent.
            Intent choiceIntentCopy = new Intent(choiceIntent);
            final boolean handled = mActivityChoserModelPolicy.onChooseActivity(this,
                    choiceIntentCopy);
            if (handled) {
                return null;
            }
        }

        HistoricalRecord historicalRecord = new HistoricalRecord(chosenName,
                System.currentTimeMillis(), DEFAULT_HISTORICAL_RECORD_WEIGHT);
        addHisoricalRecord(historicalRecord);

        return choiceIntent;
        return choiceIntent;
    }
    }


    /**
     * Sets the listener for choosing an activity.
     *
     * @param listener The listener.
     */
    public void setOnChooseActivityListener(OnChooseActivityListener listener) {
        mActivityChoserModelPolicy = listener;
    }

    /**
    /**
     * Gets the default activity, The default activity is defined as the one
     * Gets the default activity, The default activity is defined as the one
     * with highest rank i.e. the first one in the list of activities that can
     * with highest rank i.e. the first one in the list of activities that can
+32 −3
Original line number Original line Diff line number Diff line
@@ -29,6 +29,8 @@ import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.ActivityChooserModel.ActivityChooserModelClient;
import android.widget.ActivityChooserModel.ActivityChooserModelClient;


import com.android.internal.R;
import com.android.internal.R;
@@ -115,6 +117,19 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
        }
        }
    };
    };


    private final OnGlobalLayoutListener mOnGlobalLayoutListener = new OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            if (isShowingPopup()) {
                if (!isShown()) {
                    getListPopupWindow().dismiss();
                } else {
                    getListPopupWindow().show();
                }
            }
        }
    };

    /**
    /**
     * Popup window for showing the activity overflow list.
     * Popup window for showing the activity overflow list.
     */
     */
@@ -261,6 +276,8 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
            throw new IllegalStateException("No data model. Did you call #setDataModel?");
            throw new IllegalStateException("No data model. Did you call #setDataModel?");
        }
        }


        getViewTreeObserver().addOnGlobalLayoutListener(mOnGlobalLayoutListener);

        mAdapter.setMaxActivityCount(maxActivityCount);
        mAdapter.setMaxActivityCount(maxActivityCount);


        final int activityCount = mAdapter.getActivityCount();
        final int activityCount = mAdapter.getActivityCount();
@@ -292,6 +309,10 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
    public boolean dismissPopup() {
    public boolean dismissPopup() {
        if (isShowingPopup()) {
        if (isShowingPopup()) {
            getListPopupWindow().dismiss();
            getListPopupWindow().dismiss();
            ViewTreeObserver viewTreeObserver = getViewTreeObserver();
            if (viewTreeObserver.isAlive()) {
                viewTreeObserver.removeGlobalOnLayoutListener(mOnGlobalLayoutListener);
            }
        }
        }
        return true;
        return true;
    }
    }
@@ -322,6 +343,10 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
        if (dataModel != null) {
        if (dataModel != null) {
            dataModel.unregisterObserver(mModelDataSetOberver);
            dataModel.unregisterObserver(mModelDataSetOberver);
        }
        }
        ViewTreeObserver viewTreeObserver = getViewTreeObserver();
        if (viewTreeObserver.isAlive()) {
            viewTreeObserver.removeGlobalOnLayoutListener(mOnGlobalLayoutListener);
        }
        mIsAttachedToWindow = false;
        mIsAttachedToWindow = false;
    }
    }


@@ -434,8 +459,10 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
                    } else {
                    } else {
                        // The first item in the model is default action => adjust index
                        // The first item in the model is default action => adjust index
                        Intent launchIntent  = mAdapter.getDataModel().chooseActivity(position + 1);
                        Intent launchIntent  = mAdapter.getDataModel().chooseActivity(position + 1);
                        if (launchIntent != null) {
                            mContext.startActivity(launchIntent);
                            mContext.startActivity(launchIntent);
                        }
                        }
                    }
                } break;
                } break;
                default:
                default:
                    throw new IllegalArgumentException();
                    throw new IllegalArgumentException();
@@ -449,7 +476,9 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
                ResolveInfo defaultActivity = mAdapter.getDefaultActivity();
                ResolveInfo defaultActivity = mAdapter.getDefaultActivity();
                final int index = mAdapter.getDataModel().getActivityIndex(defaultActivity);
                final int index = mAdapter.getDataModel().getActivityIndex(defaultActivity);
                Intent launchIntent = mAdapter.getDataModel().chooseActivity(index);
                Intent launchIntent = mAdapter.getDataModel().chooseActivity(index);
                if (launchIntent != null) {
                    mContext.startActivity(launchIntent);
                    mContext.startActivity(launchIntent);
                }
            } else if (view == mExpandActivityOverflowButton) {
            } else if (view == mExpandActivityOverflowButton) {
                mIsSelectingDefaultActivity = false;
                mIsSelectingDefaultActivity = false;
                showPopupUnchecked(mInitialActivityCount);
                showPopupUnchecked(mInitialActivityCount);
+2 −1
Original line number Original line Diff line number Diff line
@@ -23,11 +23,11 @@ import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.util.SparseArray;
import android.view.ContextMenu;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.SoundEffectConstants;
import android.view.SoundEffectConstants;
import android.view.View;
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityEvent;




@@ -278,6 +278,7 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup {
     */
     */
    public boolean performItemClick(View view, int position, long id) {
    public boolean performItemClick(View view, int position, long id) {
        view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
        view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);

        if (mOnItemClickListener != null) {
        if (mOnItemClickListener != null) {
            playSoundEffect(SoundEffectConstants.CLICK);
            playSoundEffect(SoundEffectConstants.CLICK);
            mOnItemClickListener.onItemClick(this, view, position, id);
            mOnItemClickListener.onItemClick(this, view, position, id);
+74 −1
Original line number Original line Diff line number Diff line
@@ -28,6 +28,7 @@ import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.SubMenu;
import android.view.SubMenu;
import android.view.View;
import android.view.View;
import android.widget.ActivityChooserModel.OnChooseActivityListener;


import com.android.internal.R;
import com.android.internal.R;


@@ -72,6 +73,27 @@ import com.android.internal.R;
 */
 */
public class ShareActionProvider extends ActionProvider {
public class ShareActionProvider extends ActionProvider {


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

        /**
         * Called when a share target has been selected. The client can
         * decide whether to handle the intent or rely on the default
         * behavior which is launching it.
         * <p>
         * <strong>Note:</strong> Modifying the intent is not permitted and
         *     any changes to the latter will be ignored.
         * </p>
         *
         * @param source The source of the notification.
         * @param intent The intent for launching the chosen share target.
         * @return Whether the client has handled the intent.
         */
        public boolean onShareTargetSelected(ShareActionProvider source, Intent intent);
    }

    /**
    /**
     * The default for the maximal number of activities shown in the sub-menu.
     * The default for the maximal number of activities shown in the sub-menu.
     */
     */
@@ -103,6 +125,10 @@ public class ShareActionProvider extends ActionProvider {
     */
     */
    private String mShareHistoryFileName = DEFAULT_SHARE_HISTORY_FILE_NAME;
    private String mShareHistoryFileName = DEFAULT_SHARE_HISTORY_FILE_NAME;


    private OnShareTargetSelectedListener mOnShareTargetSelectedListener;

    private OnChooseActivityListener mOnChooseActivityListener;

    /**
    /**
     * Creates a new instance.
     * Creates a new instance.
     *
     *
@@ -113,6 +139,21 @@ public class ShareActionProvider extends ActionProvider {
        mContext = context;
        mContext = context;
    }
    }


    /**
     * 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}
     * {@inheritDoc}
     */
     */
@@ -192,6 +233,7 @@ public class ShareActionProvider extends ActionProvider {
     */
     */
    public void setShareHistoryFileName(String shareHistoryFile) {
    public void setShareHistoryFileName(String shareHistoryFile) {
        mShareHistoryFileName = shareHistoryFile;
        mShareHistoryFileName = shareHistoryFile;
        setActivityChooserPolicyIfNeeded();
    }
    }


    /**
    /**
@@ -229,8 +271,39 @@ public class ShareActionProvider extends ActionProvider {
                    mShareHistoryFileName);
                    mShareHistoryFileName);
            final int itemId = item.getItemId();
            final int itemId = item.getItemId();
            Intent launchIntent = dataModel.chooseActivity(itemId);
            Intent launchIntent = dataModel.chooseActivity(itemId);
            if (launchIntent != null) {
                mContext.startActivity(launchIntent);
                mContext.startActivity(launchIntent);
            }
            return true;
            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 ShareAcitivityChooserModelPolicy();
        }
        ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
        dataModel.setOnChooseActivityListener(mOnChooseActivityListener);
    }

    /**
     * Policy that delegates to the {@link OnShareTargetSelectedListener}, if such.
     */
    private class ShareAcitivityChooserModelPolicy implements OnChooseActivityListener {
        @Override
        public boolean onChooseActivity(ActivityChooserModel host, Intent intent) {
            if (mOnShareTargetSelectedListener != null) {
                return mOnShareTargetSelectedListener.onShareTargetSelected(
                        ShareActionProvider.this, intent);
            }
            return false;
        }
    }
}
}