I try to catch webview longclicks to show a context menu. (see code below)
When longclicking an image, I always get the image-URL as extra (for a not linked image with IMAGE_TYPE and for a linked image with SRC_IMAGE_ANCHOR_TYPE).
But how can I get the Link-URL (and not the image-URL) for an image with a hyperlink?
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;
}
});
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.
Instead of calling this function myWebView.requestFocusNodeHref(msg);
, try calling this function myWebView.requestImageRef(msg);