Injecting Javascript into a Webview outside the onPageFinished Event (Using DatePicker to set a date on an input of a WebView)

前端 未结 1 1446
萌比男神i
萌比男神i 2021-01-17 04:18

I have an Android app, running a WebView that loads a certain page, also part of the app. I want to use the Android DatePicker to get a date from the user and set the value

1条回答
  •  忘掉有多难
    2021-01-17 04:49

    Thanks @CommonsWare for the comment, i tracked the error and got this:

    "android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views."

    Googled it and got this forum thread

    So, in order to update a view in the UI at runtime and outside it's thread, you have to use a Handler, that receive messages and execute actions accordingly.

    So i implemented a Handler for the Activity, that gets a message with an int identifier and the data i want to update into the webview:

    final Handler handler = new Handler() {
        public void handleMessage(Message msg) {
    
            int cod = msg.getData().getInt("messageType");
            switch(cod){
                case 1:
                    String date = msg.getData().getString("datePickerValue");
                    mWebView.loadUrl("javascript:setReturnDate('" + mId + "', '" + date + "');");
                    break;
                case 2:
                    showDialog(0);
                    break;
            }
    
        }
    };
    

    I had to change the openDatePicker method of the class to use the Handler, as well as create an input parameter, which is the id of the control in the page:

    public void openDatePicker(String id){
    
            mId = id; //mId is a string declared in the Activity scope, so it can be used anywhere
            Message msg = new Message();
            Bundle b = new Bundle();
            b.putInt("messageType", 2);
    
            msg.setData(b);
            handler.sendMessage(msg);
        }
    

    Rewrote the DatePicker listener for the date selection, to get the data and send a message to the Handler:

    private DatePickerDialog.OnDateSetListener mDateSetListener =
        new DatePickerDialog.OnDateSetListener() {
    
            public void onDateSet(DatePicker view, int year, 
                                  int monthOfYear, int dayOfMonth) {
    
                Message msg = new Message();
                Bundle b = new Bundle();
                b.putInt("messageType", 1);
                b.putString("datePickerValue", 
                        String.format("%02d", dayOfMonth) + "/" + 
                        String.format("%02d", (monthOfYear + 1)) + "/" + 
                        String.valueOf(year));
                msg.setData(b);
                handler.sendMessage(msg);
            }
        };
    

    In the webpage, the js functions got out like this:

    function openDatePicker(id) {
            if (objAndroid != null) objAndroid.openDatePicker(id);
        }
    
        function setReturnDate(id, date) {
            var obj = document.getElementById(id);
            if (obj != null)
                obj.value = date;
        }
    

    And finally, the input (TextBox), got like this:

    TextBox obj = FindControl("txtDt") as TextBox;
    
                if (obj != null)
                {
                    obj.Attributes.Add("readonly", "readonly");
                    obj.Attributes.Add("OnClick", "javascript:openDatePicker(this.id)");
                }
    

    0 讨论(0)
提交回复
热议问题