The problem: calling webview.hitTestResult
on an anchor tag that has an image as a child element returns a hitTestResult
with the type of SRC_IMAGE_ANCHOR_TYPE
and the hitTestResult.extra
is the src
of the image and not the url
of the anchor tag.
In order to get the url
of the anchor tag it is necessary to call an additional method on the WebView
. The function to call is requestFocusNodeHref. This function takes a Message
as its only parameter.
The following stackoverflow answer suggest how this can be used in order to achieve the desired result - How to get link-URL in Android WebView with HitTestResult for a linked image (and not the image-URL) with Longclick
In the answer the following code snip-it is provided (converted to Kotlin, and tweaked slightly):
mWebview.setOnLongClickListener {
val result = mWebview.hitTestResult
if (result.type == HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
val msg = mHandler.obtainMessage()
mWebview.requestFocusNodeHref(msg)
}
false
}
and the Handler to get the URL:
val mHandler = object : Handler() {
override fun handleMessage(msg: Message) {
// Get link-URL.
val url = msg.data.getString("url")
// Do something with it.
if (url != null) { ... }
}
}
However, the problem with this approach is that in order to ensure no leaks the Handler needs to be declared as a static and any references back to the outer class need to use WeakReference
.
Since this Handler is declared as an inner class, it may prevent the outer class from being garbage collected….
See ADT 20 Preview 3 for info on when this Lint rule was added.
There is an alternative way to use the Handler
and Message
to mitigate this.
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
}
}
If you also want to get the src
of the image this is available in the message bundle as src
message.data.getString("src")
. Additionally, title
and alt
are also available.
This flow was taken from the WebKitHitTestTest test which has the following test case to cover getting the anchor tag from a SRC_IMAGE_ANCHOR_TYPE
hit target - srcImgeAnchorTypeTestBody
private void srcImgeAnchorTypeTestBody(boolean byTouch) throws Throwable {
String fullImageSrc = "http://foo.bar/nonexistent.jpg";
String page = CommonResources.makeHtmlPageFrom("", "<a class=\"full_view\" href=\""
+ HREF + "\"onclick=\"return false;\"><img class=\"full_view\" src=\""
+ fullImageSrc + "\"></a>");
setServerResponseAndLoad(page);
simulateInput(byTouch);
pollForHitTestDataOnUiThread(HitTestResult.SRC_IMAGE_ANCHOR_TYPE, fullImageSrc);
pollForHrefAndImageSrcOnUiThread(HREF, null, fullImageSrc);
}