Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android WebView JellyBean -> Should not happen: no rect-based-test nodes found

My application is using a lot of webviews which are lying in fragments which are hold by a ViewPager.

Whenever i swipe through the app on my Galaxy Nexus with Jellybean on it i get the following console message again and again:

08-23 13:44:03.374: E/webcoreglue(21690): Should not happen: no rect-based-test nodes found

Can anyone explain to me what is going wrong here so that i might be able to fix the issue?

like image 557
Ostkontentitan Avatar asked Aug 23 '12 11:08

Ostkontentitan


4 Answers

The issue occurs because in some scenarios WebView fails to notice that its visible rect has changed, so as far as webkit is concerned the page is still not visible. Thus all touches fall outside of the window, and get rejected.

The cleanest fix is when you know the visibility of your WebView has changed (such as in response to a setPrimaryItem callback from a viewpager), call webview.onScrollChanged(webview.getScrollX(), webview.getScrollY());

You will need to subclass the webview to promote the protected onScrollChanged to a public method.

like image 115
John Reck Avatar answered Sep 28 '22 06:09

John Reck


I had this exact issue. The problem is exactly what Rahul Dole said in his answer above.

I spend a few days on this trying tons of different things. I noticed that when the orientation changed that the visible WebView onLongClick worked again...so I came up with this little gem. Indeed its very hacky but it works!

Use this in your class that extends WebView:

@Override
public boolean onTouchEvent(MotionEvent event) {

    if (event.getAction() == MotionEvent.ACTION_DOWN){

        int temp_ScrollY = getScrollY();
        scrollTo(getScrollX(), getScrollY() + 1);
        scrollTo(getScrollX(), temp_ScrollY);

    }

    return super.onTouchEvent(event);
}
like image 26
Codeversed Avatar answered Sep 28 '22 08:09

Codeversed


I faced exactly the same problem. In my app wherever i had click events coded using 'touchend' in jquery bind(), this error was coming up and it used to never respond to clicks (taps).. and gave a frozen kind of feel. So I just tried replacing 'touchend' with 'click' in bind(), and it worked! responded to clicks (Taps) and also didn't show that log entry of webcoreglue..

I also found this piece of code in Android's webview code..

HTMLElement* WebViewCore::retrieveElement(int x, int y,
    const QualifiedName& tagName)
{
    HitTestResult hitTestResult = m_mainFrame->eventHandler()
        ->hitTestResultAtPoint(IntPoint(x, y), false, false,
        DontHitTestScrollbars, HitTestRequest::Active | HitTestRequest::ReadOnly,
        IntSize(1, 1));
    if (!hitTestResult.innerNode() || !hitTestResult.innerNode()->inDocument()) {
        LOGE("Should not happen: no in document Node found");
        return 0;
    }
    const ListHashSet<RefPtr<Node> >& list = hitTestResult.rectBasedTestResult();
    if (list.isEmpty()) {
        LOGE("Should not happen: no rect-based-test nodes found");
        return 0;
    }
    Node* node = hitTestResult.innerNode();
    Node* element = node;
    while (element && (!element->isElementNode()
        || !element->hasTagName(tagName))) {
        element = element->parentNode();
    }
    DBG_NAV_LOGD("node=%p element=%p x=%d y=%d nodeName=%s tagName=%s", node,
        element, x, y, node->nodeName().utf8().data(),
        element ? ((Element*) element)->tagName().utf8().data() : "<none>");
    return static_cast<WebCore::HTMLElement*>(element);
}​

and this too..

// get the highlight rectangles for the touch point (x, y) with the slop
Vector<IntRect> WebViewCore::getTouchHighlightRects(int x, int y, int slop)
{
    Vector<IntRect> rects;
    m_mousePos = IntPoint(x - m_scrollOffsetX, y - m_scrollOffsetY);
    HitTestResult hitTestResult = m_mainFrame->eventHandler()->hitTestResultAtPoint(IntPoint(x, y),
            false, false, DontHitTestScrollbars, HitTestRequest::Active | HitTestRequest::ReadOnly, IntSize(slop, slop));
    if (!hitTestResult.innerNode() || !hitTestResult.innerNode()->inDocument()) {
        LOGE("Should not happen: no in document Node found");
        return rects;
    }
    const ListHashSet<RefPtr<Node> >& list = hitTestResult.rectBasedTestResult();
    if (list.isEmpty()) {
        LOGE("Should not happen: no rect-based-test nodes found");
        return rects;
    }
//Rest of the part is omitted here...

Notice that log message there? I am guessing this code is for identifying the x and y axis vectors generated on clicks or taps or swipes.. ​

like image 33
Rahul Dole Avatar answered Sep 28 '22 07:09

Rahul Dole


Have the same problem with JellyBean and ViewPager + fragments that contains WebViews. And all OK with the same code running on Android 2.2, so I think this is a bug in JB WebView implementation.

On JB only the first shown fragment with WebView works right, without errors "Should not happen .." in the log, and getHitTestResult() calls returns correct values. Swiping to the next pages, I got errors in log and getHitTestResult() returns only zeroes and nulls.

Now I found only one solution to create fragments with empty containers and create WebViews, setup they and load data only when current fragment becomes active in the ViewPager. In this case WebView works as needed. But, unfortunately, this completely breaks an idea of smooth swiping pages in the ViewPager.

Have the last idea, tomorrow will try to replace ViewPager's fragments to compound views. Little chances, but I'll let you know if results will be successful.

like image 29
Vlad Kuts Avatar answered Sep 28 '22 06:09

Vlad Kuts