2

Im trying to evaluateJavascript query with blocking function in my webview. Meaning function thread awaits result. However, evaluateJavascript and ValueCallback are both called on main thread, and main thread is paused awaiting for result, meaning result can never be caught with await. Here is my example,

private String getFirstUser(){
    String evS = "document.getElementsByClassName(\"hm-user\")[0].innerHTML";
    final CountDownLatch cdl = new CountDownLatch(1);
    final StringBuilder sb = new StringBuilder();
    try{
        evaluateJavascript(evS, new ValueCallback<String>() {
            @Override
            public void onReceiveValue(String value) {
                if(value != null && value.length() != 0 && !value.equals("null")){
                    sb.append(value);
                }
                cdl.countDown();
            }
        });
        cdl.await(200, TimeUnit.MILLISECONDS);
    }catch (Exception e){};
    return sb.length() == 0 ? null : sb.toString();
}

What happens is, callback does not happen until await is unblocked, meaning function always return null?

What am I doing wrong? I have used this for http requests and it worked.

Edit: I am aware of similiar threads like Android main thread blocking WebView thread however, there are no solutions available.

Jonzi
  • 141
  • 1
  • 2
  • 13

1 Answers1

1

Since the call onReceiveValue won't be synchronous and would involve blocking your main Thread in case you want to make it synchronous, I would recommend you to avoid doing it. Instead of trying to implement it as synchronous call, implement callbacks and let it continue as asynchronous.

You can achieve it as follows:

private void getFirstUser(final ValueCallback<String> valueCallback){
    String evS = "document.getElementsByClassName(\"hm-user\")[0].innerHTML";    
    final StringBuilder sb = new StringBuilder();
    try{
        evaluateJavascript(evS, valueCallback);
    }catch (Exception e){ 
        valueCallback.onReceiveValue(null);// You can pass any value instead of null.
    };

}

While calling method simply do:

getFirstUser(new ValueCallback<String>() {
            @Override
            public void onReceiveValue(String value) {
                if(value != null && value.length() != 0 && !value.equals("null")){
                   //do something with proper value
                }else{
                  // take necessary action if value is null
                }

            }
        });
Sagar
  • 23,903
  • 4
  • 62
  • 62
  • Making it non blocking, is opposite of my initial intent, but if there is no other way, I will do it like this. If only I could call evaluate from non UI thread. – Jonzi Jun 23 '18 at 07:54
  • @Jonzi You can try calling evaluate from non-UI thread. I am not sure if that will work. But `onReceiveValue` executes on main thread. You might have issues with state of `CountDownLatch` from different Threads. – Sagar Jun 23 '18 at 07:56
  • I have tried, but most of WebView functions specifically say they want to be executed on UI thread, throwing exception otherwise. There is a check function checkThread() in WebView.java that does this check, but it cannot be overriden as it is private – Jonzi Jun 23 '18 at 08:03
  • @Jonzi then no choice, you have to go for asynchronous way – Sagar Jun 23 '18 at 08:04
  • Alright, I have an idea that should work, but is some ugly code and will only work in my case. :s Let's say I had method something() that called getFirstUser(), what I can do now is split something() to somethingPt1() that calls getFirstUser(), which then calls somethingPt2() to continue workflow. It's really shitty solution, but I that's the only way I see – Jonzi Jun 23 '18 at 08:09
  • @Jonzi its almost similar to what I have implemented in callback. Instead of `somethingPt2()` use `onReceiveValue` and since the `getFirstUser` is capable of receiving `ValueCallback` you can actually perform it with ease by initializing the `ValueCallback` – Sagar Jun 23 '18 at 08:13
  • yeah, removing blocking requirement results in similar solution one way or another. Thanks for your help – Jonzi Jun 23 '18 at 08:19
  • @Jonzi no problem. Enjoy coding :-) +1 for your quesiton – Sagar Jun 23 '18 at 08:21