@Test @SdkSuppress(minSdkVersion = 26, maxSdkVersion = 27) public void testSetCustomSelectionActionModeCallback_fixesBugInO() { final PackageManager packageManagerMock = spy(mTextView.getContext().getPackageManager()); final Context contextMock = spy(mTextView.getContext()); when(contextMock.getPackageManager()).thenReturn(packageManagerMock); final TextView tvMock = spy(mTextView); try { final Field contextField = View.class.getDeclaredField("mContext"); contextField.setAccessible(true); contextField.set(tvMock, contextMock); } catch (NoSuchFieldException | IllegalAccessException e) { assertTrue(false); } final ResolveInfo info1 = new ResolveInfo(); info1.activityInfo = new ActivityInfo(); info1.activityInfo.packageName = contextMock.getPackageName(); info1.activityInfo.name = "Activity 1"; info1.nonLocalizedLabel = "Option 3"; final ResolveInfo info2 = new ResolveInfo(); info2.activityInfo = new ActivityInfo(); info2.activityInfo.packageName = contextMock.getPackageName(); info2.activityInfo.name = "Activity 2"; info2.nonLocalizedLabel = "Option 4"; final ResolveInfo info3 = new ResolveInfo(); info3.activityInfo = new ActivityInfo(); info3.activityInfo.packageName = contextMock.getPackageName(); info3.activityInfo.name = "Activity 3"; info3.nonLocalizedLabel = "Option 5"; final List<ResolveInfo> infos = Arrays.asList(info1, info2, info3); doAnswer(new Answer() { @Override public Object answer(final InvocationOnMock invocation) throws Throwable { final Intent intent = invocation.getArgument(0); if (Intent.ACTION_PROCESS_TEXT.equals(intent.getAction())) { return infos; } return invocation.callRealMethod(); } }).when(packageManagerMock).queryIntentActivities((Intent) any(), anyInt()); TextViewCompat.setCustomSelectionActionModeCallback(tvMock, new ActionMode.Callback() { @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { return true; } @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return true; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { return true; } @Override public void onDestroyActionMode(ActionMode mode) { } }); final Menu menu = new MenuBuilder(tvMock.getContext()); menu.add(Menu.NONE, Menu.NONE, 1, "Option 1"); menu.add(Menu.NONE, Menu.NONE, 2, "Option 2"); menu.add(Menu.NONE, Menu.NONE, 100, "Option 3") .setIntent(new Intent(Intent.ACTION_PROCESS_TEXT)); menu.add(Menu.NONE, Menu.NONE, 101, "Option 5") .setIntent(new Intent(Intent.ACTION_PROCESS_TEXT)); tvMock.getCustomSelectionActionModeCallback().onPrepareActionMode(null, menu); assertEquals(5, menu.size()); for (int i = 0; i < menu.size(); ++i) { assertEquals("Option " + (i + 1), menu.getItem(i).getTitle()); } }
public static void setCustomSelectionActionModeCallback(@NonNull final TextView textView, @NonNull final ActionMode.Callback callback) { if (Build.VERSION.SDK_INT < 26 || Build.VERSION.SDK_INT > 27) { textView.setCustomSelectionActionModeCallback(callback); return; } textView.setCustomSelectionActionModeCallback(new OreoCallback(callback, textView)); }
TextViewCompat { public static void setCustomSelectionActionModeCallback(@NonNull final TextView textView, @NonNull final ActionMode.Callback callback) { if (Build.VERSION.SDK_INT < 26 || Build.VERSION.SDK_INT > 27) { textView.setCustomSelectionActionModeCallback(callback); return; } textView.setCustomSelectionActionModeCallback(new OreoCallback(callback, textView)); } }
TextViewCompat { public static void setCustomSelectionActionModeCallback(@NonNull final TextView textView, @NonNull final ActionMode.Callback callback) { if (Build.VERSION.SDK_INT < 26 || Build.VERSION.SDK_INT > 27) { textView.setCustomSelectionActionModeCallback(callback); return; } textView.setCustomSelectionActionModeCallback(new OreoCallback(callback, textView)); } private  TextViewCompat(); }
TextViewCompat { public static void setCustomSelectionActionModeCallback(@NonNull final TextView textView, @NonNull final ActionMode.Callback callback) { if (Build.VERSION.SDK_INT < 26 || Build.VERSION.SDK_INT > 27) { textView.setCustomSelectionActionModeCallback(callback); return; } textView.setCustomSelectionActionModeCallback(new OreoCallback(callback, textView)); } private  TextViewCompat(); static void setCompoundDrawablesRelative(@NonNull TextView textView,
            @Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end,
            @Nullable Drawable bottom); static void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView,
            @Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end,
            @Nullable Drawable bottom); static void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView,
            @DrawableRes int start, @DrawableRes int top, @DrawableRes int end,
            @DrawableRes int bottom); static int getMaxLines(@NonNull TextView textView); static int getMinLines(@NonNull TextView textView); static void setTextAppearance(@NonNull TextView textView, @StyleRes int resId); @NonNull static Drawable[] getCompoundDrawablesRelative(@NonNull TextView textView); @SuppressWarnings("RedundantCast") // Intentionally invoking interface method. static void setAutoSizeTextTypeWithDefaults(@NonNull TextView textView,
            int autoSizeTextType); @SuppressWarnings("RedundantCast") // Intentionally invoking interface method. static void setAutoSizeTextTypeUniformWithConfiguration(
            @NonNull TextView textView,
            int autoSizeMinTextSize,
            int autoSizeMaxTextSize,
            int autoSizeStepGranularity,
            int unit); @SuppressWarnings("RedundantCast") // Intentionally invoking interface method. static void setAutoSizeTextTypeUniformWithPresetSizes(@NonNull TextView textView,
            @NonNull int[] presetSizes, int unit); @SuppressWarnings("RedundantCast") // Intentionally invoking interface method. static int getAutoSizeTextType(@NonNull TextView textView); @SuppressWarnings("RedundantCast") // Intentionally invoking interface method. static int getAutoSizeStepGranularity(@NonNull TextView textView); @SuppressWarnings("RedundantCast") // Intentionally invoking interface method. static int getAutoSizeMinTextSize(@NonNull TextView textView); @SuppressWarnings("RedundantCast") // Intentionally invoking interface method. static int getAutoSizeMaxTextSize(@NonNull TextView textView); @NonNull @SuppressWarnings("RedundantCast") // Intentionally invoking interface method. static int[] getAutoSizeTextAvailableSizes(@NonNull TextView textView); static void setCustomSelectionActionModeCallback(@NonNull final TextView textView,
                @NonNull final ActionMode.Callback callback); static void setFirstBaselineToTopHeight(
            @NonNull final TextView textView,
            @Px @IntRange(from = 0) final int firstBaselineToTopHeight); static void setLastBaselineToBottomHeight(
            @NonNull final TextView textView,
            @Px @IntRange(from = 0) int lastBaselineToBottomHeight); static int getFirstBaselineToTopHeight(@NonNull final TextView textView); static int getLastBaselineToBottomHeight(@NonNull final TextView textView); static void setLineHeight(@NonNull final TextView textView,
                              @Px @IntRange(from = 0) int lineHeight); }
TextViewCompat { public static void setCustomSelectionActionModeCallback(@NonNull final TextView textView, @NonNull final ActionMode.Callback callback) { if (Build.VERSION.SDK_INT < 26 || Build.VERSION.SDK_INT > 27) { textView.setCustomSelectionActionModeCallback(callback); return; } textView.setCustomSelectionActionModeCallback(new OreoCallback(callback, textView)); } private  TextViewCompat(); static void setCompoundDrawablesRelative(@NonNull TextView textView,
            @Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end,
            @Nullable Drawable bottom); static void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView,
            @Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end,
            @Nullable Drawable bottom); static void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView,
            @DrawableRes int start, @DrawableRes int top, @DrawableRes int end,
            @DrawableRes int bottom); static int getMaxLines(@NonNull TextView textView); static int getMinLines(@NonNull TextView textView); static void setTextAppearance(@NonNull TextView textView, @StyleRes int resId); @NonNull static Drawable[] getCompoundDrawablesRelative(@NonNull TextView textView); @SuppressWarnings("RedundantCast") // Intentionally invoking interface method. static void setAutoSizeTextTypeWithDefaults(@NonNull TextView textView,
            int autoSizeTextType); @SuppressWarnings("RedundantCast") // Intentionally invoking interface method. static void setAutoSizeTextTypeUniformWithConfiguration(
            @NonNull TextView textView,
            int autoSizeMinTextSize,
            int autoSizeMaxTextSize,
            int autoSizeStepGranularity,
            int unit); @SuppressWarnings("RedundantCast") // Intentionally invoking interface method. static void setAutoSizeTextTypeUniformWithPresetSizes(@NonNull TextView textView,
            @NonNull int[] presetSizes, int unit); @SuppressWarnings("RedundantCast") // Intentionally invoking interface method. static int getAutoSizeTextType(@NonNull TextView textView); @SuppressWarnings("RedundantCast") // Intentionally invoking interface method. static int getAutoSizeStepGranularity(@NonNull TextView textView); @SuppressWarnings("RedundantCast") // Intentionally invoking interface method. static int getAutoSizeMinTextSize(@NonNull TextView textView); @SuppressWarnings("RedundantCast") // Intentionally invoking interface method. static int getAutoSizeMaxTextSize(@NonNull TextView textView); @NonNull @SuppressWarnings("RedundantCast") // Intentionally invoking interface method. static int[] getAutoSizeTextAvailableSizes(@NonNull TextView textView); static void setCustomSelectionActionModeCallback(@NonNull final TextView textView,
                @NonNull final ActionMode.Callback callback); static void setFirstBaselineToTopHeight(
            @NonNull final TextView textView,
            @Px @IntRange(from = 0) final int firstBaselineToTopHeight); static void setLastBaselineToBottomHeight(
            @NonNull final TextView textView,
            @Px @IntRange(from = 0) int lastBaselineToBottomHeight); static int getFirstBaselineToTopHeight(@NonNull final TextView textView); static int getLastBaselineToBottomHeight(@NonNull final TextView textView); static void setLineHeight(@NonNull final TextView textView,
                              @Px @IntRange(from = 0) int lineHeight); static final int AUTO_SIZE_TEXT_TYPE_NONE; static final int AUTO_SIZE_TEXT_TYPE_UNIFORM; }