How to get link URL in Android WebView using HitTestResult for linked image (not image URL) using Longclick

I am trying to catch webview longclicks to show a context menu. (see code below) With a long click on the image, I always get the image URL as an additional one (for an unlinked image with IMAGE_TYPE and a linked image with SRC_IMAGE_ANCHOR_TYPE). But how can I get the link url (and not the image url) for a hyperlinked image?

Best, Sebastian

mywebview.setOnLongClickListener(new OnLongClickListener() { public boolean onLongClick(View v) { final WebView webview = (WebView) v; final WebView.HitTestResult result = webview.getHitTestResult(); if (result.getType() == SRC_ANCHOR_TYPE) { return true; } if (result.getType() == SRC_IMAGE_ANCHOR_TYPE) { return true; } if (result.getType() == IMAGE_TYPE) { return true; } return false; } }); 
+4
source share
4 answers

I checked the source code of the WebView and it seems that the uri of the image is the only extra data that you can get for SRC_IMAGE_ANCHOR_TYPE. But fear not, 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 junior Android 2.1 device and a high-end Android 4.0 device, both work like a charm.

Hello

Ziteng chen

+5
source

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

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) ... } }; 
+15
source

Ziteng Chen solution works up to Android 4.0 (API level 15), but for some reason KeyEvent does not work in LEVEL 16+ API (Android 4.1+ JELLY_BEAN). It does not start loading WebView loadUrl. So I had to replace dispatchKeyEvent dispatchTouchEvent. Here is 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 probably have to wait (use AsyncTask) to get mUrl on slower devices, where it is right after running dispatchTouchEvents

Hope this helps.

+1
source

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

-1
source

All Articles