Search code examples
androidandroid-webviewandroid-6.0-marshmallow

startActionMode (on text select) in WebView called in KitKat but not in Marshmallow


I use an

@Override public ActionMode startActionMode(Callback callback) {

to intercept text selection in a WebView. Unfortunately, this code that works in Android 4.0.4 ICS and Android 4.4.4 KitKat does not work on Android 6.0.1, Marshmallow.

On Android 6.0.1, the debug lines inside the overridden methods of the callback (onCreateActionMode(), onPrepareActionMode(), onActionItemClicked() ...) are not called when the user long taps on a word in the text.

I post below the code to reproduce the issue.

A class MainActivity :

package com.example.test07;

import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        String s = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ";
        String c = "<p>"+s+s+s+"</p>"+"<p>"+s+s+"</p>";

        WebView gd_web = (WebView) findViewById(R.id.gd_web);

        gd_web.loadDataWithBaseURL("file:///", c, "text/html", "utf-8", null);
    }

}

A class CustomWebView :

package com.example.test07;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
import android.view.ActionMode.Callback;
import android.webkit.WebView;


public class CustomWebView extends WebView {

    public CustomWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }

    @Override
    public ActionMode startActionMode(Callback callback) {
        Log.w("TEST", "ææ startActionMode");
        return super.startActionMode(new ActionMode.Callback() {
            @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                Log.w("TEST", "ææ onCreateActionMode");
                return false;
            }

            @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                Log.w("TEST", "ææ onPrepareActionMode");
                return false;
            }

            @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
                Log.w("TEST", "ææ onActionItemClicked");
                return false;
            }

            @Override public void onDestroyActionMode(ActionMode mode) {

            }

        });
    }

}

and a test layout activity_main.xml :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    tools:context="${relativePackage}.${activityClass}" >

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="--" />

    <com.example.test07.CustomWebView
         android:layout_width="match_parent"
         android:layout_height="0dp"
         android:layout_weight="1"
         android:id="@+id/gd_web"
        />
</LinearLayout>

How to make this code work on recent Android versions?


Solution

  • Recent versions of Android call the startActionMode(ActionMode.Callback, int) version of this method.

    https://issuetracker.google.com/issues/79394037

    Also, on API level 17 and 19, the WebView is very different from current WebView, Chromium based update-able WebView is on L and above, so we can't do anything for that. That's probably why startActionMode() wasn't called on these devices.

    On the other hand, if you want to support API leve 23 and above, you will also need to override the other startActionMode(ActionMode.Callback, int).