How to get link-URL in Android WebView with HitTestResult for a linked image (and not the image-URL) with Longclick

不想你离开。 提交于 2019-11-28 23:59:35

I checked the source code of the WebView and it seems that the image uri is the only extra data you can get for SRC_IMAGE_ANCHOR_TYPE. But don't be mad here I have a quick and dirty workaround for you:

    webview.setOnLongClickListener(new OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            final WebView webview = (WebView) v;
            final HitTestResult result = webview.getHitTestResult();
            if(result.getType()==HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
                webview.setWebViewClient(new WebViewClient(){
                    @Override
                    public boolean shouldOverrideUrlLoading(WebView view, String url) {
                        // 2. and here we get the url (remember to remove the WebView client and return true so that the hyperlink will not be really triggered)
                        mUrl = url; // mUrl is a member variant of the activity
                        view.setWebViewClient(null);
                        return true;
                    }
                });
                // 1. the picture must be focused, so we simulate a DPAD enter event to trigger the hyperlink
                KeyEvent event1 = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
                webview.dispatchKeyEvent(event1);
                KeyEvent event2 = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER);
                webview.dispatchKeyEvent(event2);
                // 3. now you can do something with the anchor url (and then clear the mUrl for future usage)
                String url = mUrl;
                if (url!=null) {
                    Toast.makeText(webview.getContext(), url, Toast.LENGTH_SHORT).show();
                }

                mUrl = null;
            }
            return false;
        }
    });

I tried the code on a low-end Android 2.1 device and a high-end Android 4.0 device, both work like a charm.

Regards

Ziteng Chen

None of solutions above worked for me on Android 4.2.2. So I looked into source code of default android web browser. I extracted solution to this exact problem - get link-URL from image link.

Source: https://github.com/android/platform_packages_apps_browser/blob/master/src/com/android/browser/Controller.java

Extracted solution:

LongClick listener:

...
mWebview.setOnLongClickListener(new OnLongClickListener() {

    @Override
    public boolean onLongClick(View v) {
        HitTestResult result = mWebview.getHitTestResult();
        if (result.getType() == HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
            Message msg = mHandler.obtainMessage();
            mWebview.requestFocusNodeHref(msg);
        }
    }
});
...

Handler to get the URL:

private Handler mHandler = new Handler() {

    @Override
        public void handleMessage(Message msg) {
            // Get link-URL.
            String url = (String) msg.getData().get("url");

            // Do something with it.
            if (url != null) ...
        }
    };

I know this is an old issue, but I recently came across this issue. Based on Perry_ml answer, I used the following Kotlin code to resolve it:

webView.setOnLongClickListener {
    val result = webView.hitTestResult
    if (result.type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
        val handler = Handler()
        val message = handler.obtainMessage()

        webView.requestFocusNodeHref(message)
        val url = message.data.getString("url")

        // Do something with url, return true as touch has been handled
        true
    } else {
        false
    }
}

I posted some information about it here.

Ziteng Chen solution works up to Android 4.0 (API Level 15) but for some reason the KeyEvent down & up doesn't work in API LEVEL 16+ (Android 4.1+ JELLY_BEAN). It doesn't fire the WebView's loadUrl. So I had to replace the dispatchKeyEvent with dispatchTouchEvent. Here's the code:

...
MotionEvent touchDown = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, touchX, touchY, 0);
webView.dispatchTouchEvent(touchDown);
touchDown.recycle();

MotionEvent touchUp = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, touchX, touchY, 0);
webView.dispatchTouchEvent(touchUp);
touchUp.recycle();

String url = mUrl;
...

You'd probably have to wait (use an AsyncTask) to get the mUrl in slower devices where it's null immediately after firing the dispatchTouchEvents

Hope it helps.

user3367850

Instead of calling this function myWebView.requestFocusNodeHref(msg);, try calling this function myWebView.requestImageRef(msg);

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!