14

i want allow user to select some texts from webview and it need to be send as a text message. pls find way to select text and copy to clipboard and extracting from clipboard. i saw many example but nothing helped me really...TIA

Edit
using the code provided in the link from @orangmoney52. with following changes

getmethod's second parameter and invoke method second parameter. if i give null there warning will come.. which one is correct?

 public void selectAndCopyText() {
     try {
         Method m = WebView.class.getMethod("emulateShiftHeld", Boolean.TYPE); 
            m.invoke(BookView.mWebView, false); 
        } catch (Exception e) {
            e.printStackTrace();
            // fallback
            KeyEvent shiftPressEvent = new KeyEvent(0,0,
                 KeyEvent.ACTION_DOWN,KeyEvent.KEYCODE_SHIFT_LEFT,0,0);
            shiftPressEvent.dispatch(this);
        }

}

Getting this error:

 05-26 16:41:01.121: WARN/System.err(1096): java.lang.NoSuchMethodException: emulateShiftHeld  
vnshetty
  • 20,051
  • 23
  • 64
  • 102

4 Answers4

13

The above answers looks perfectly fine and it seems you're missing something while selecting text. So you need to double check the code and find your overridden any TouchEvent of webview.

i Tried below code it works fine...

Function is

 private void emulateShiftHeld(WebView view)
    {
        try
        {
            KeyEvent shiftPressEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
                                                    KeyEvent.KEYCODE_SHIFT_LEFT, 0, 0);
            shiftPressEvent.dispatch(view);
            Toast.makeText(this, "select_text_now", Toast.LENGTH_SHORT).show();
        }
        catch (Exception e)
        {
            Log.e("dd", "Exception in emulateShiftHeld()", e);
        }
    }

Call Above method wherever you want (You can put a button and call this method in its click event): emulateShiftHeld(mWebView);

Ken
  • 30,811
  • 34
  • 116
  • 155
vnshetty
  • 20,051
  • 23
  • 64
  • 102
12

Step: 1 Create custom WebView class. This class will override the native action bar on long press on the webview text. Also it handles the the selection case for different version of android (tested on 4.0 onwards) This code takes the selected text using javascript.

public class CustomWebView extends WebView {
private Context context;
// override all other constructor to avoid crash
public CustomWebView(Context context) {
    super(context);
    this.context = context;
    WebSettings webviewSettings = getSettings();
    webviewSettings.setJavaScriptEnabled(true);
    // add JavaScript interface for copy
    addJavascriptInterface(new WebAppInterface(context), "JSInterface");
}

// setting custom action bar
private ActionMode mActionMode;
private ActionMode.Callback mSelectActionModeCallback;
private GestureDetector mDetector;

// this will over ride the default action bar on long press
@Override
public ActionMode startActionMode(Callback callback) {
    ViewParent parent = getParent();
    if (parent == null) {
        return null;
    }
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
        String name = callback.getClass().toString();
        if (name.contains("SelectActionModeCallback")) {
            mSelectActionModeCallback = callback;
            mDetector = new GestureDetector(context,
                    new CustomGestureListener());
        }
    }
    CustomActionModeCallback mActionModeCallback = new CustomActionModeCallback();
    return parent.startActionModeForChild(this, mActionModeCallback);
}

private class CustomActionModeCallback implements ActionMode.Callback {

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        mActionMode = mode;
        MenuInflater inflater = mode.getMenuInflater();
        inflater.inflate(R.menu.menu, menu);
        return true;
    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return false; 
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {

        switch (item.getItemId()) {
        case R.id.copy:
            getSelectedData();
            mode.finish(); 
            return true;
        case R.id.share:
            mode.finish();
            return true;
        default:
            mode.finish();
            return false;
        }
    }
    @Override
    public void onDestroyActionMode(ActionMode mode) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            clearFocus();
        }else{
             if (mSelectActionModeCallback != null) {
                 mSelectActionModeCallback.onDestroyActionMode(mode);
             }
             mActionMode = null;
        }
    }
}
private void getSelectedData(){

    String js= "(function getSelectedText() {"+
            "var txt;"+
            "if (window.getSelection) {"+
                "txt = window.getSelection().toString();"+
            "} else if (window.document.getSelection) {"+
                "txt = window.document.getSelection().toString();"+
            "} else if (window.document.selection) {"+
                "txt = window.document.selection.createRange().text;"+
            "}"+
            "JSInterface.getText(txt);"+
          "})()";
    // calling the js function
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        evaluateJavascript("javascript:"+js, null);
    }else{
        loadUrl("javascript:"+js);
    }
}

private class CustomGestureListener extends GestureDetector.SimpleOnGestureListener {
    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        if (mActionMode != null) {
            mActionMode.finish();
            return true;
        }
        return false;
    }
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    // Send the event to our gesture detector
    // If it is implemented, there will be a return value
    if(mDetector !=null)
        mDetector.onTouchEvent(event);
    // If the detected gesture is unimplemented, send it to the superclass
    return super.onTouchEvent(event);
}

}

Step 2: create separate class for WebView interface. This class listnes for event from once javascript code is getting executed

public class WebAppInterface {
Context mContext;

WebAppInterface(Context c) {
    mContext = c;
}

@JavascriptInterface
public void getText(String text) {
    // put selected text into clipdata
    ClipboardManager clipboard = (ClipboardManager)
            mContext.getSystemService(Context.CLIPBOARD_SERVICE);
    ClipData clip = ClipData.newPlainText("simple text",text);
    clipboard.setPrimaryClip(clip);
    // gives the toast for selected text
    Toast.makeText(mContext, text, Toast.LENGTH_SHORT).show();
}
}

Step 3: Add menu.xml for custom menu in res > menu folder

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
    android:id="@+id/copy"
    android:icon="@drawable/ic_action_copy"
    android:showAsAction="always" 
    android:title="copy">
</item>
<item
    android:id="@+id/share"
    android:icon="@drawable/ic_action_share"
    android:showAsAction="always" 
    android:title="share">
</item>

I took help of several links listed below to achieve this: Thanks to you guys.

how to use javascript on webview http://developer.android.com/guide/webapps/webview.html#UsingJavaScript

for injecting javascript Why can't I inject this javascript in the webview on android?

for overriding default action bar How to override default text selection of android webview os 4.1+?

for version 4.0. to 4.3 text selection Webview text selection not clearing

Community
  • 1
  • 1
vikoo
  • 2,451
  • 20
  • 27
5

The easiest way, although not as pretty as what seems like a per manufacturer implemented copy/paste feature, is the following:

https://bugzilla.wikimedia.org/show_bug.cgi?id=31484

Basically, if you're setting your own WebChromeClient via webview.setWebChromeClient(...) then text selection is disabled by default. To enable it your WebChromeClient needs to have to following method implemented:

//@Override
/**
* Tell the client that the selection has been initiated.
*/
public void onSelectionStart(WebView view) {
    // Parent class aborts the selection, which seems like a terrible default.
    //Log.i("DroidGap", "onSelectionStart called");
}
biegleux
  • 13,179
  • 11
  • 45
  • 52
Leo K
  • 808
  • 1
  • 9
  • 24
  • In my case it is also not workng.I am overriding onTouch() but it returning false. What was the real problem, did you overrided touch events.? – Dev.Sinto May 29 '13 at 12:06
  • My suggestion was not to override onTouch(). Are you settings your own, custom, WebChromeClient? – Leo K May 29 '13 at 16:40
  • What are you talking about? WebChromeClient does not have an "onSelectionStart" according to http://developer.android.com/reference/android/webkit/WebChromeClient.html. How is this even working (it actually is!) despite the fact that Eclipse warns me that this function isn't used anywhere (and it isn't in the API.) – Michael Sep 26 '14 at 22:22
  • 1
    It has that method it's just not exposed (hidden) take a look at the source code in `WebChromeClient` if you're curious. Basically it's hidden, but that doesn't stop you from overriding it. This is all less pertinent now since there's a new WebView starting with Android 4.4 – Leo K Sep 28 '14 at 20:49
  • It seems this answer does not apply for Android >= KitKat 4.4 (API 19). – Antônio Medeiros Aug 08 '18 at 13:17
  • Well the question was asked in 2011 and my answer was in 2012 so yeah things change :) – Leo K Aug 09 '18 at 00:46
0

@vnshetty, using the code provided in the link from @orangmoney52, I was able to complete this problem a few months ago. You can create a button in your menu that allows you to copy text. Then, in onOptionsItemSelected, you can have a clause like this:

    case R.id.select_and_copy: {
        Toast.makeText(getApplicationContext(), "Select Text", Toast.LENGTH_SHORT).show();
        selectAndCopyText();
        return true;
    }
Phil
  • 35,852
  • 23
  • 123
  • 164
  • Yes After toast is displayed i pressed shift key and try to select the webview content using mouse but nothing is selected? Am i missing anything? – vnshetty May 26 '11 at 11:08
  • There's no need to press the shift key. Simply select the text after the toast message is displayed. – Phil May 26 '11 at 19:55