分享

android - Injecting Javascript into a Webview...

 earthworm 2011-02-21

Hey experts,

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 on an input inside the page in the WebView.

The DatePickerDialog opens when the user clicks the input, but when i get the return of the date selection, i can't run the loadUrl method to set the value in the input, it gives me an error and the app crashes.

A little bit of code (It's a test code, so don't mind if it is a bit out of context):

Class i provide to the WebView:

public class webViewInterface { 
   
public void openDatePicker(){ 
        showDialog
(0); 
   
} 
} 

Javascript function on the page, called on the click of the input:

function openDatePicker() { 
       
if (objAndroid != null) objAndroid.openDatePicker(); 
   
} 

Listener for the date selection

private DatePickerDialog.OnDateSetListener mDateSetListener = 
   
new DatePickerDialog.OnDateSetListener() { 
 
       
public void onDateSet(DatePicker view, int year,  
                             
int monthOfYear, int dayOfMonth) { 
 
            mWebView
.loadUrl("javascript:setReturnDate();"); 
       
} 
   
}; 

Javascript function that sets a value on the input

function setReturnDate() { 
        document
.getElementById('txtAgency').value = '9999'; 
   
} 

Any ideas?

Thanks in advance.

link|edit|flag
@M42C3L0: Use adb logcat, DDMS, or the DDMS perspective in Eclipse to examine LogCat and look at the stack trace associated with your error. – CommonsWare Feb 8 at 13:19

1 Answer

up vote 0 down vote accepted

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)"); 
           
} 
link|edit|flag

Your Answer

 
or
never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.

Hello World!

This is a collaboratively edited question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

about ?   faq ?

tagged

 × 76847
 × 42138
 × 697
 × 154

asked

13 days ago

viewed

95 times

latest activity

7 days ago

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多