0

I'm new to Android and I stuck. I have a Textview on Activity which should show result, but for some reason it is updating TextView only if you click on Button which is not doing anything or if you close app and reopen it again from menu of running apps. I suppose it's somehow connected with updating activity. Thank you in advance!

package com.example.visacheck;

import android.content.Intent;
import android.os.Bundle;
import android.webkit.JavascriptInterface;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

public class FourthActivity extends AppCompatActivity {

    String aplicationNumber;
    String type;
    String year;


    @Override
    protected void onCreate(Bundle savedInstanceState) {

        this.getSupportActionBar().hide();
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fourth);

        Intent intent = getIntent();
        final Button button = findViewById(R.id.resultButton); //Result appearing only after clicking button

        aplicationNumber =  intent.getStringExtra("aplicationNumber");
        type = intent.getStringExtra("type");
        year = intent.getStringExtra("year");

            class MyJavaScriptInterface {
                @JavascriptInterface
                @SuppressWarnings("unused")
                public void processHTML(String html) {
                    TextView text = findViewById(R.id.textView);
                    text.setText(html);
                }
            }


            final WebView myWebview = findViewById(R.id.webview);
            myWebview.getSettings().setJavaScriptEnabled(true);
            myWebview.addJavascriptInterface(new MyJavaScriptInterface(), "HTMLOUT");

            myWebview.setWebViewClient(new WebViewClient() {
                @Override
                public void onPageFinished(WebView view, String url) {

                    myWebview.loadUrl(("javascript:document.getElementById('edit-ioff-application-number').value = '" + aplicationNumber + "';void(0);"));
                    myWebview.loadUrl(("javascript:" + "document.getElementById('edit-ioff-application-code').value = '" + type + "';void(0);"));
                    myWebview.loadUrl(("javascript:document.getElementById('edit-ioff-application-year').value = '" + year + "';void(0);"));
                    myWebview.loadUrl(("javascript:document.getElementById('edit-submit-button').click();"));
                    myWebview.loadUrl("javascript:window.HTMLOUT.processHTML(document.getElementsByClassName('alert alert-warning')[0].innerText);");
                    myWebview.loadUrl("javascript:window.HTMLOUT.processHTML(document.getElementsByClassName('alert alert-success')[1].innerText);");
                    myWebview.loadUrl("javascript:window.HTMLOUT.processHTML(document.getElementsByClassName('alert alert-danger')[0].innerText);");

                }
            });
            myWebview.loadUrl("https://frs.gov.cz/ioff/application-status");
    }

}
Bonuseto
  • 19
  • 5
  • Can you share what the button is doing in onClick? – Khodor Jan 17 '20 at 14:41
  • It's funny part, there is no onClick method, this button don't doing anything only exist, but if you click on it, TextView is refreshing – Bonuseto Jan 17 '20 at 15:09
  • Do you mean the textview that is set from the html? When you load the page it hasn't finished loading the html yet, hence the textview is not yet set, when you open it from running apps it resumes and already has the data. – Sharone Lev Jan 17 '20 at 15:10
  • Could you try this? `myWebView.post(new Runnable() { @Override public void run() { TextView text = findViewById(R.id.textView); text.setText(html); });` insde your processHTML function – Khodor Jan 17 '20 at 15:19
  • @sharone-lev I think you are right, but how I can set condition to update textview only when html finaly loaded? – Bonuseto Jan 17 '20 at 15:48
  • @Khodor [link](https://ibb.co/CJYpjnq), I'm trying, but something not right – Bonuseto Jan 17 '20 at 15:52
  • @Bonuseto You have to declare `myWebview ` BEFORE this line. Try moving this line `final WebView myWebview = findViewById(R.id.webview);` above your `class MyJavaScriptInterface { ...` EDIT: Here is a corrected version of the code. `myWebView.post(new Runnable() { @Override public void run() { TextView text = findViewById(R.id.textView); text.setText(html); }});` – Khodor Jan 17 '20 at 15:58
  • @Khodor I tried but still getting same result [link](https://ibb.co/w67YtS7) – Bonuseto Jan 17 '20 at 16:03
  • @Bonuseto This is a syntax problem. I just missed a curly brace at the end of the line. Please check the correct version and replace it with your current one. – Khodor Jan 17 '20 at 16:07
  • @Khodor thank you so much! It's working now, but could you tell me what we are doing with this line which you have provided? – Bonuseto Jan 17 '20 at 16:19

1 Answers1

1

I'm not going to do a very good job at this, as I can hardly touch on the subject myself. Maybe someone with more knowledge can go into further detail, but the general idea here is that this code is being called by the JS thread as opposed to your UI thread (Which is the only thread that is allowed to handle UI updates), and I'm surprised this code doesn't crash when doing so, honestly. The post() method adds this to the view's message queue, which means that the text will be updated AFTER the view has been rendered, and has no other tasks to perform. I know I did a bad job at explaining this, but for more information, please refer to these:

What exactly does the post method do?

Alternately, you can user runOnUIThread(), example:

How do we use runOnUiThread in Android?

I'm sure that a lot of people out there have already explained this better than I have. But the most important thing to understand here is that you must not update UI from anything other than the UI thread

Please note that I chose myWebView arbitrarily, and this should work if posted to the fragment's main view aswell.

class MyJavaScriptInterface {
        @JavascriptInterface
        @SuppressWarnings("unused")
        public void processHTML(final String html) {
            myWebview.post(new Runnable() {
                @Override public void run() {
                    TextView text = findViewById(R.id.textView); text.setText(html);
                }
            });
        }
    }
Khodor
  • 129
  • 1
  • 7