Loading core/java/com/android/internal/app/ChooserActivity.java +43 −10 Original line number Diff line number Diff line Loading @@ -111,6 +111,7 @@ import com.android.internal.app.ResolverListAdapter.ActivityInfoPresentationGett import com.android.internal.app.ResolverListAdapter.ViewHolder; import com.android.internal.app.chooser.ChooserTargetInfo; import com.android.internal.app.chooser.DisplayResolveInfo; import com.android.internal.app.chooser.MultiDisplayResolveInfo; import com.android.internal.app.chooser.NotSelectableTargetInfo; import com.android.internal.app.chooser.SelectableTargetInfo; import com.android.internal.app.chooser.SelectableTargetInfo.SelectableTargetInfoCommunicator; Loading Loading @@ -1352,17 +1353,31 @@ public class ChooserActivity extends ResolverActivity implements return getIntent().getBooleanExtra(Intent.EXTRA_AUTO_LAUNCH_SINGLE_CHOICE, true); } @Override public void showTargetDetails(ResolveInfo ri) { if (ri == null) { void showTargetDetails(TargetInfo ti) { if (ti == null) { return; } ComponentName name = ri.activityInfo.getComponentName(); ComponentName name = ti.getResolveInfo().activityInfo.getComponentName(); boolean pinned = mPinnedSharedPrefs.getBoolean(name.flattenToString(), false); ResolverTargetActionsDialogFragment f = new ResolverTargetActionsDialogFragment(ri.loadLabel(getPackageManager()), name, pinned); ResolverTargetActionsDialogFragment f; // For multiple targets, include info on all targets if (ti instanceof MultiDisplayResolveInfo) { MultiDisplayResolveInfo mti = (MultiDisplayResolveInfo) ti; List<CharSequence> labels = new ArrayList<>(); for (TargetInfo innerInfo : mti.getTargets()) { labels.add(innerInfo.getResolveInfo().loadLabel(getPackageManager())); } f = new ResolverTargetActionsDialogFragment( mti.getResolveInfo().loadLabel(getPackageManager()), name, mti.getTargets(), labels); } else { f = new ResolverTargetActionsDialogFragment( ti.getResolveInfo().loadLabel(getPackageManager()), name, pinned); } f.show(getFragmentManager(), TARGET_DETAILS_FRAGMENT_TAG); } Loading Loading @@ -1416,8 +1431,26 @@ public class ChooserActivity extends ResolverActivity implements } final long selectionCost = System.currentTimeMillis() - mChooserShownTime; // Stacked apps get a disambiguation first if (targetInfo instanceof MultiDisplayResolveInfo) { MultiDisplayResolveInfo mti = (MultiDisplayResolveInfo) targetInfo; CharSequence[] labels = new CharSequence[mti.getTargets().size()]; int i = 0; for (TargetInfo ti : mti.getTargets()) { labels[i++] = ti.getResolveInfo().loadLabel(getPackageManager()); } ChooserStackedAppDialogFragment f = new ChooserStackedAppDialogFragment( targetInfo.getDisplayLabel(), ((MultiDisplayResolveInfo) targetInfo).getTargets(), labels); f.show(getFragmentManager(), TARGET_DETAILS_FRAGMENT_TAG); return; } super.startSelected(which, always, filtered); if (currentListAdapter.getCount() > 0) { // Log the index of which type of target the user picked. // Lower values mean the ranking was better. Loading Loading @@ -2363,7 +2396,7 @@ public class ChooserActivity extends ResolverActivity implements itemView.setOnLongClickListener(v -> { showTargetDetails( mChooserMultiProfilePagerAdapter.getActiveListAdapter() .resolveInfoForPosition(mListPosition, /* filtered */ true)); .targetInfoForPosition(mListPosition, /* filtered */ true)); return true; }); } Loading Loading @@ -2615,7 +2648,7 @@ public class ChooserActivity extends ResolverActivity implements @Override public boolean onLongClick(View v) { showTargetDetails( mChooserListAdapter.resolveInfoForPosition( mChooserListAdapter.targetInfoForPosition( holder.getItemIndex(column), true)); return true; } Loading core/java/com/android/internal/app/ChooserListAdapter.java +25 −2 Original line number Diff line number Diff line Loading @@ -38,17 +38,22 @@ import com.android.internal.R; import com.android.internal.app.ResolverActivity.ResolvedComponentInfo; import com.android.internal.app.chooser.ChooserTargetInfo; import com.android.internal.app.chooser.DisplayResolveInfo; import com.android.internal.app.chooser.MultiDisplayResolveInfo; import com.android.internal.app.chooser.SelectableTargetInfo; import com.android.internal.app.chooser.TargetInfo; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; public class ChooserListAdapter extends ResolverListAdapter { private static final String TAG = "ChooserListAdapter"; private static final boolean DEBUG = false; private boolean mEnableStackedApps = true; public static final int NO_POSITION = -1; public static final int TARGET_BAD = -1; public static final int TARGET_CALLER = 0; Loading Loading @@ -218,7 +223,25 @@ public class ChooserListAdapter extends ResolverListAdapter { void updateAlphabeticalList() { mSortedList.clear(); if (mEnableStackedApps) { // Consolidate multiple targets from same app. Map<String, DisplayResolveInfo> consolidated = new HashMap<>(); for (DisplayResolveInfo info : mDisplayList) { String packageName = info.getResolvedComponentName().getPackageName(); if (consolidated.get(packageName) != null) { // create consolidated target MultiDisplayResolveInfo multiDisplayResolveInfo = new MultiDisplayResolveInfo(packageName, info); multiDisplayResolveInfo.addTarget(consolidated.get(packageName)); consolidated.put(packageName, multiDisplayResolveInfo); } else { consolidated.put(packageName, info); } } mSortedList.addAll(consolidated.values()); } else { mSortedList.addAll(mDisplayList); } Collections.sort(mSortedList, new ChooserActivity.AzInfoComparator(mContext)); } Loading Loading @@ -270,7 +293,7 @@ public class ChooserListAdapter extends ResolverListAdapter { } int getAlphaTargetCount() { int standardCount = super.getCount(); int standardCount = mSortedList.size(); return standardCount > mChooserListCommunicator.getMaxRankedTargets() ? standardCount : 0; } Loading core/java/com/android/internal/app/ChooserStackedAppDialogFragment.java 0 → 100644 +86 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * 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 com.android.internal.app; import android.app.AlertDialog.Builder; import android.app.Dialog; import android.app.DialogFragment; import android.content.DialogInterface; import android.content.res.Configuration; import android.os.Bundle; import com.android.internal.app.chooser.DisplayResolveInfo; import java.util.ArrayList; import java.util.List; /** * Shows individual actions for a "stacked" app target - such as an app with multiple posting * streams represented in the Sharesheet. */ public class ChooserStackedAppDialogFragment extends DialogFragment implements DialogInterface.OnClickListener { private static final String TITLE_KEY = "title"; private static final String PINNED_KEY = "pinned"; private List<DisplayResolveInfo> mTargetInfos = new ArrayList<>(); private CharSequence[] mLabels; public ChooserStackedAppDialogFragment() { } public ChooserStackedAppDialogFragment(CharSequence title) { Bundle args = new Bundle(); args.putCharSequence(TITLE_KEY, title); setArguments(args); } public ChooserStackedAppDialogFragment(CharSequence title, List<DisplayResolveInfo> targets, CharSequence[] labels) { Bundle args = new Bundle(); args.putCharSequence(TITLE_KEY, title); mTargetInfos = targets; mLabels = labels; setArguments(args); } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final Bundle args = getArguments(); return new Builder(getContext()) .setCancelable(true) .setItems(mLabels, this) .setTitle(args.getCharSequence(TITLE_KEY)) .create(); } @Override public void onClick(DialogInterface dialog, int which) { final Bundle args = getArguments(); mTargetInfos.get(which).start(getActivity(), null); dismiss(); } @Override public void onConfigurationChanged(Configuration newConfig) { // Dismiss on config changed (eg: rotation) // TODO: Maintain state on config change super.onConfigurationChanged(newConfig); dismiss(); } } core/java/com/android/internal/app/ResolverActivity.java +1 −1 Original line number Diff line number Diff line Loading @@ -1160,7 +1160,7 @@ public class ResolverActivity extends Activity implements return !target.isSuspended(); } public void showTargetDetails(ResolveInfo ri) { void showTargetDetails(ResolveInfo ri) { Intent in = new Intent().setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) .setData(Uri.fromParts("package", ri.activityInfo.packageName, null)) .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); Loading core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java +73 −22 Original line number Diff line number Diff line Loading @@ -24,14 +24,19 @@ import android.content.ComponentName; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Configuration; import android.net.Uri; import android.os.Bundle; import android.provider.Settings; import com.android.internal.R; import com.android.internal.app.chooser.DisplayResolveInfo; import java.util.ArrayList; import java.util.List; /** * Shows a dialog with actions to take on a chooser target * Shows a dialog with actions to take on a chooser target. */ public class ResolverTargetActionsDialogFragment extends DialogFragment implements DialogInterface.OnClickListener { Loading @@ -43,6 +48,10 @@ public class ResolverTargetActionsDialogFragment extends DialogFragment private static final int TOGGLE_PIN_INDEX = 0; private static final int APP_INFO_INDEX = 1; private List<DisplayResolveInfo> mTargetInfos = new ArrayList<>(); private List<CharSequence> mLabels = new ArrayList<>(); private boolean[] mPinned; public ResolverTargetActionsDialogFragment() { } Loading @@ -55,15 +64,43 @@ public class ResolverTargetActionsDialogFragment extends DialogFragment setArguments(args); } public ResolverTargetActionsDialogFragment(CharSequence title, ComponentName name, List<DisplayResolveInfo> targets, List<CharSequence> labels) { Bundle args = new Bundle(); args.putCharSequence(TITLE_KEY, title); args.putParcelable(NAME_KEY, name); mTargetInfos = targets; mLabels = labels; setArguments(args); } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final Bundle args = getArguments(); final int itemRes = args.getBoolean(PINNED_KEY, false) ? R.array.resolver_target_actions_unpin : R.array.resolver_target_actions_pin; String[] defaultActions = getResources().getStringArray(itemRes); CharSequence[] items; if (mTargetInfos == null || mTargetInfos.size() < 2) { items = defaultActions; } else { // Pin item for each sub-item items = new CharSequence[mTargetInfos.size() + 1]; for (int i = 0; i < mTargetInfos.size(); i++) { items[i] = mTargetInfos.get(i).isPinned() ? getResources().getString(R.string.unpin_specific_target, mLabels.get(i)) : getResources().getString(R.string.pin_specific_target, mLabels.get(i)); } // "App info" items[mTargetInfos.size()] = defaultActions[1]; } return new Builder(getContext()) .setCancelable(true) .setItems(itemRes, this) .setItems(items, this) .setTitle(args.getCharSequence(TITLE_KEY)) .create(); } Loading @@ -72,27 +109,41 @@ public class ResolverTargetActionsDialogFragment extends DialogFragment public void onClick(DialogInterface dialog, int which) { final Bundle args = getArguments(); ComponentName name = args.getParcelable(NAME_KEY); switch (which) { case TOGGLE_PIN_INDEX: SharedPreferences sp = ChooserActivity.getPinnedSharedPrefs(getContext()); final String key = name.flattenToString(); boolean currentVal = sp.getBoolean(name.flattenToString(), false); if (currentVal) { sp.edit().remove(key).apply(); if (which == 0 || (mTargetInfos.size() > 0 && which < mTargetInfos.size())) { if (mTargetInfos == null || mTargetInfos.size() == 0) { pinComponent(name); } else { sp.edit().putBoolean(key, true).apply(); pinComponent(mTargetInfos.get(which).getResolvedComponentName()); } // Force the chooser to requery and resort things getActivity().recreate(); break; case APP_INFO_INDEX: } else { // Last item in dialog is App Info Intent in = new Intent().setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) .setData(Uri.fromParts("package", name.getPackageName(), null)) .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); startActivity(in); break; } dismiss(); } private void pinComponent(ComponentName name) { SharedPreferences sp = ChooserActivity.getPinnedSharedPrefs(getContext()); final String key = name.flattenToString(); boolean currentVal = sp.getBoolean(name.flattenToString(), false); if (currentVal) { sp.edit().remove(key).apply(); } else { sp.edit().putBoolean(key, true).apply(); } } @Override public void onConfigurationChanged(Configuration newConfig) { // Dismiss on config changed (eg: rotation) // TODO: Maintain state on config change super.onConfigurationChanged(newConfig); dismiss(); } } Loading
core/java/com/android/internal/app/ChooserActivity.java +43 −10 Original line number Diff line number Diff line Loading @@ -111,6 +111,7 @@ import com.android.internal.app.ResolverListAdapter.ActivityInfoPresentationGett import com.android.internal.app.ResolverListAdapter.ViewHolder; import com.android.internal.app.chooser.ChooserTargetInfo; import com.android.internal.app.chooser.DisplayResolveInfo; import com.android.internal.app.chooser.MultiDisplayResolveInfo; import com.android.internal.app.chooser.NotSelectableTargetInfo; import com.android.internal.app.chooser.SelectableTargetInfo; import com.android.internal.app.chooser.SelectableTargetInfo.SelectableTargetInfoCommunicator; Loading Loading @@ -1352,17 +1353,31 @@ public class ChooserActivity extends ResolverActivity implements return getIntent().getBooleanExtra(Intent.EXTRA_AUTO_LAUNCH_SINGLE_CHOICE, true); } @Override public void showTargetDetails(ResolveInfo ri) { if (ri == null) { void showTargetDetails(TargetInfo ti) { if (ti == null) { return; } ComponentName name = ri.activityInfo.getComponentName(); ComponentName name = ti.getResolveInfo().activityInfo.getComponentName(); boolean pinned = mPinnedSharedPrefs.getBoolean(name.flattenToString(), false); ResolverTargetActionsDialogFragment f = new ResolverTargetActionsDialogFragment(ri.loadLabel(getPackageManager()), name, pinned); ResolverTargetActionsDialogFragment f; // For multiple targets, include info on all targets if (ti instanceof MultiDisplayResolveInfo) { MultiDisplayResolveInfo mti = (MultiDisplayResolveInfo) ti; List<CharSequence> labels = new ArrayList<>(); for (TargetInfo innerInfo : mti.getTargets()) { labels.add(innerInfo.getResolveInfo().loadLabel(getPackageManager())); } f = new ResolverTargetActionsDialogFragment( mti.getResolveInfo().loadLabel(getPackageManager()), name, mti.getTargets(), labels); } else { f = new ResolverTargetActionsDialogFragment( ti.getResolveInfo().loadLabel(getPackageManager()), name, pinned); } f.show(getFragmentManager(), TARGET_DETAILS_FRAGMENT_TAG); } Loading Loading @@ -1416,8 +1431,26 @@ public class ChooserActivity extends ResolverActivity implements } final long selectionCost = System.currentTimeMillis() - mChooserShownTime; // Stacked apps get a disambiguation first if (targetInfo instanceof MultiDisplayResolveInfo) { MultiDisplayResolveInfo mti = (MultiDisplayResolveInfo) targetInfo; CharSequence[] labels = new CharSequence[mti.getTargets().size()]; int i = 0; for (TargetInfo ti : mti.getTargets()) { labels[i++] = ti.getResolveInfo().loadLabel(getPackageManager()); } ChooserStackedAppDialogFragment f = new ChooserStackedAppDialogFragment( targetInfo.getDisplayLabel(), ((MultiDisplayResolveInfo) targetInfo).getTargets(), labels); f.show(getFragmentManager(), TARGET_DETAILS_FRAGMENT_TAG); return; } super.startSelected(which, always, filtered); if (currentListAdapter.getCount() > 0) { // Log the index of which type of target the user picked. // Lower values mean the ranking was better. Loading Loading @@ -2363,7 +2396,7 @@ public class ChooserActivity extends ResolverActivity implements itemView.setOnLongClickListener(v -> { showTargetDetails( mChooserMultiProfilePagerAdapter.getActiveListAdapter() .resolveInfoForPosition(mListPosition, /* filtered */ true)); .targetInfoForPosition(mListPosition, /* filtered */ true)); return true; }); } Loading Loading @@ -2615,7 +2648,7 @@ public class ChooserActivity extends ResolverActivity implements @Override public boolean onLongClick(View v) { showTargetDetails( mChooserListAdapter.resolveInfoForPosition( mChooserListAdapter.targetInfoForPosition( holder.getItemIndex(column), true)); return true; } Loading
core/java/com/android/internal/app/ChooserListAdapter.java +25 −2 Original line number Diff line number Diff line Loading @@ -38,17 +38,22 @@ import com.android.internal.R; import com.android.internal.app.ResolverActivity.ResolvedComponentInfo; import com.android.internal.app.chooser.ChooserTargetInfo; import com.android.internal.app.chooser.DisplayResolveInfo; import com.android.internal.app.chooser.MultiDisplayResolveInfo; import com.android.internal.app.chooser.SelectableTargetInfo; import com.android.internal.app.chooser.TargetInfo; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; public class ChooserListAdapter extends ResolverListAdapter { private static final String TAG = "ChooserListAdapter"; private static final boolean DEBUG = false; private boolean mEnableStackedApps = true; public static final int NO_POSITION = -1; public static final int TARGET_BAD = -1; public static final int TARGET_CALLER = 0; Loading Loading @@ -218,7 +223,25 @@ public class ChooserListAdapter extends ResolverListAdapter { void updateAlphabeticalList() { mSortedList.clear(); if (mEnableStackedApps) { // Consolidate multiple targets from same app. Map<String, DisplayResolveInfo> consolidated = new HashMap<>(); for (DisplayResolveInfo info : mDisplayList) { String packageName = info.getResolvedComponentName().getPackageName(); if (consolidated.get(packageName) != null) { // create consolidated target MultiDisplayResolveInfo multiDisplayResolveInfo = new MultiDisplayResolveInfo(packageName, info); multiDisplayResolveInfo.addTarget(consolidated.get(packageName)); consolidated.put(packageName, multiDisplayResolveInfo); } else { consolidated.put(packageName, info); } } mSortedList.addAll(consolidated.values()); } else { mSortedList.addAll(mDisplayList); } Collections.sort(mSortedList, new ChooserActivity.AzInfoComparator(mContext)); } Loading Loading @@ -270,7 +293,7 @@ public class ChooserListAdapter extends ResolverListAdapter { } int getAlphaTargetCount() { int standardCount = super.getCount(); int standardCount = mSortedList.size(); return standardCount > mChooserListCommunicator.getMaxRankedTargets() ? standardCount : 0; } Loading
core/java/com/android/internal/app/ChooserStackedAppDialogFragment.java 0 → 100644 +86 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * 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 com.android.internal.app; import android.app.AlertDialog.Builder; import android.app.Dialog; import android.app.DialogFragment; import android.content.DialogInterface; import android.content.res.Configuration; import android.os.Bundle; import com.android.internal.app.chooser.DisplayResolveInfo; import java.util.ArrayList; import java.util.List; /** * Shows individual actions for a "stacked" app target - such as an app with multiple posting * streams represented in the Sharesheet. */ public class ChooserStackedAppDialogFragment extends DialogFragment implements DialogInterface.OnClickListener { private static final String TITLE_KEY = "title"; private static final String PINNED_KEY = "pinned"; private List<DisplayResolveInfo> mTargetInfos = new ArrayList<>(); private CharSequence[] mLabels; public ChooserStackedAppDialogFragment() { } public ChooserStackedAppDialogFragment(CharSequence title) { Bundle args = new Bundle(); args.putCharSequence(TITLE_KEY, title); setArguments(args); } public ChooserStackedAppDialogFragment(CharSequence title, List<DisplayResolveInfo> targets, CharSequence[] labels) { Bundle args = new Bundle(); args.putCharSequence(TITLE_KEY, title); mTargetInfos = targets; mLabels = labels; setArguments(args); } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final Bundle args = getArguments(); return new Builder(getContext()) .setCancelable(true) .setItems(mLabels, this) .setTitle(args.getCharSequence(TITLE_KEY)) .create(); } @Override public void onClick(DialogInterface dialog, int which) { final Bundle args = getArguments(); mTargetInfos.get(which).start(getActivity(), null); dismiss(); } @Override public void onConfigurationChanged(Configuration newConfig) { // Dismiss on config changed (eg: rotation) // TODO: Maintain state on config change super.onConfigurationChanged(newConfig); dismiss(); } }
core/java/com/android/internal/app/ResolverActivity.java +1 −1 Original line number Diff line number Diff line Loading @@ -1160,7 +1160,7 @@ public class ResolverActivity extends Activity implements return !target.isSuspended(); } public void showTargetDetails(ResolveInfo ri) { void showTargetDetails(ResolveInfo ri) { Intent in = new Intent().setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) .setData(Uri.fromParts("package", ri.activityInfo.packageName, null)) .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); Loading
core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java +73 −22 Original line number Diff line number Diff line Loading @@ -24,14 +24,19 @@ import android.content.ComponentName; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Configuration; import android.net.Uri; import android.os.Bundle; import android.provider.Settings; import com.android.internal.R; import com.android.internal.app.chooser.DisplayResolveInfo; import java.util.ArrayList; import java.util.List; /** * Shows a dialog with actions to take on a chooser target * Shows a dialog with actions to take on a chooser target. */ public class ResolverTargetActionsDialogFragment extends DialogFragment implements DialogInterface.OnClickListener { Loading @@ -43,6 +48,10 @@ public class ResolverTargetActionsDialogFragment extends DialogFragment private static final int TOGGLE_PIN_INDEX = 0; private static final int APP_INFO_INDEX = 1; private List<DisplayResolveInfo> mTargetInfos = new ArrayList<>(); private List<CharSequence> mLabels = new ArrayList<>(); private boolean[] mPinned; public ResolverTargetActionsDialogFragment() { } Loading @@ -55,15 +64,43 @@ public class ResolverTargetActionsDialogFragment extends DialogFragment setArguments(args); } public ResolverTargetActionsDialogFragment(CharSequence title, ComponentName name, List<DisplayResolveInfo> targets, List<CharSequence> labels) { Bundle args = new Bundle(); args.putCharSequence(TITLE_KEY, title); args.putParcelable(NAME_KEY, name); mTargetInfos = targets; mLabels = labels; setArguments(args); } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final Bundle args = getArguments(); final int itemRes = args.getBoolean(PINNED_KEY, false) ? R.array.resolver_target_actions_unpin : R.array.resolver_target_actions_pin; String[] defaultActions = getResources().getStringArray(itemRes); CharSequence[] items; if (mTargetInfos == null || mTargetInfos.size() < 2) { items = defaultActions; } else { // Pin item for each sub-item items = new CharSequence[mTargetInfos.size() + 1]; for (int i = 0; i < mTargetInfos.size(); i++) { items[i] = mTargetInfos.get(i).isPinned() ? getResources().getString(R.string.unpin_specific_target, mLabels.get(i)) : getResources().getString(R.string.pin_specific_target, mLabels.get(i)); } // "App info" items[mTargetInfos.size()] = defaultActions[1]; } return new Builder(getContext()) .setCancelable(true) .setItems(itemRes, this) .setItems(items, this) .setTitle(args.getCharSequence(TITLE_KEY)) .create(); } Loading @@ -72,27 +109,41 @@ public class ResolverTargetActionsDialogFragment extends DialogFragment public void onClick(DialogInterface dialog, int which) { final Bundle args = getArguments(); ComponentName name = args.getParcelable(NAME_KEY); switch (which) { case TOGGLE_PIN_INDEX: SharedPreferences sp = ChooserActivity.getPinnedSharedPrefs(getContext()); final String key = name.flattenToString(); boolean currentVal = sp.getBoolean(name.flattenToString(), false); if (currentVal) { sp.edit().remove(key).apply(); if (which == 0 || (mTargetInfos.size() > 0 && which < mTargetInfos.size())) { if (mTargetInfos == null || mTargetInfos.size() == 0) { pinComponent(name); } else { sp.edit().putBoolean(key, true).apply(); pinComponent(mTargetInfos.get(which).getResolvedComponentName()); } // Force the chooser to requery and resort things getActivity().recreate(); break; case APP_INFO_INDEX: } else { // Last item in dialog is App Info Intent in = new Intent().setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) .setData(Uri.fromParts("package", name.getPackageName(), null)) .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); startActivity(in); break; } dismiss(); } private void pinComponent(ComponentName name) { SharedPreferences sp = ChooserActivity.getPinnedSharedPrefs(getContext()); final String key = name.flattenToString(); boolean currentVal = sp.getBoolean(name.flattenToString(), false); if (currentVal) { sp.edit().remove(key).apply(); } else { sp.edit().putBoolean(key, true).apply(); } } @Override public void onConfigurationChanged(Configuration newConfig) { // Dismiss on config changed (eg: rotation) // TODO: Maintain state on config change super.onConfigurationChanged(newConfig); dismiss(); } }