2010-08-31 37 views
16

Tôi đã bắt đầu viết một ứng dụng cung cấp cho người dùng biểu mẫu HTML qua WebView. Vì biểu mẫu không nằm trong tầm kiểm soát của tôi, dữ liệu được điền vào có thể được gửi dưới dạng yêu cầu GET hoặc POST. Ứng dụng của tôi là bắt buộc để nắm bắt dữ liệu biểu mẫu được vận chuyển, tức là, giữ lại những gì đã được nhập vào các trường biểu mẫu.có thể truy cập dữ liệu biểu mẫu HTML được đăng thông qua WebView không?

Sử dụng gọi lại đầy đủ từ WebViewClient chẳng hạn như onPageLoaded(), thật dễ dàng để nắm bắt dữ liệu biểu mẫu từ yêu cầu GET. Tuy nhiên, tôi không thể tìm thấy bất kỳ phương thức thích hợp nào để cho phép cùng một dữ liệu đã đăng, tức là, có thể truy cập vào nội dung thư HTTP POST chứa dữ liệu biểu mẫu. Tôi có thiếu một cuộc gọi lại có liên quan ở đây hay không đơn giản là không có cách nào để hoàn thành mục tiêu được chỉ định với API đã cho (ngay cả cấp 8 mới nhất)?

Giả sử nó không thể, tôi coi trọng và mở rộng các phần của android.webkit để giới thiệu một móc gọi lại mới được truyền qua cơ thể POST bằng cách nào đó. Bằng cách đó, ứng dụng của tôi có thể được vận chuyển bằng trình duyệt tùy chỉnh/WebViewClient đáp ứng được tính năng mong muốn. Tuy nhiên, tôi không thể tìm thấy bất kỳ vị trí nào tốt để bắt đầu bằng mã và sẽ rất vui vì bất kỳ gợi ý nào trong trường hợp này (trong trường hợp cách tiếp cận có vẻ đầy hứa hẹn).

Cảm ơn trước!

+0

Thực ra, tôi có thể đã tìm ra một cách bản thân mình: Nó phải có khả năng tiêm một số JavaScript mà phân tích các các trường biểu mẫu khi người dùng gửi biểu mẫu. Giao diện Javascript-to-Java được cung cấp sau đó sẽ có khả năng chuyển dữ liệu đã điền trở lại vào không gian Java để xử lý tiếp. Sẽ thử cách tiếp cận đó và báo cáo lại. Tất nhiên, bất kỳ phản hồi nào khác vẫn được hoan nghênh! –

Trả lời

22

Như được nêu trong nhận xét của riêng tôi đối với câu hỏi ban đầu, phương pháp tiêm JavaScript hoạt động. Về cơ bản, những gì bạn cần làm là thêm một số đoạn mã JavaScript vào sự kiện DOM onsubmit, để nó phân tích cú pháp các trường của biểu mẫu và trả về kết quả về hàm Java đã đăng ký.

Mã dụ:

public class MyBrowser extends Activity { 
    private final String jsInjectCode = 
     "function parseForm(event) {" + 
     " var form = this;" + 
     " // make sure form points to the surrounding form object if a custom button was used" + 
     " if (this.tagName.toLowerCase() != 'form')" + 
     "  form = this.form;" +  
     " var data = '';" + 
     " if (!form.method) form.method = 'get';" + 
     " data += 'method=' + form.method;" + 
     " data += '&action=' + form.action;" +   
     " var inputs = document.forms[0].getElementsByTagName('input');" + 
     " for (var i = 0; i < inputs.length; i++) {" + 
     "   var field = inputs[i];" + 
     "   if (field.type != 'submit' && field.type != 'reset' && field.type != 'button')" + 
     "    data += '&' + field.name + '=' + field.value;" + 
     " }" + 
     " HTMLOUT.processFormData(data);" + 
     "}" + 
     "" + 
     "for (var form_idx = 0; form_idx < document.forms.length; ++form_idx)" + 
     " document.forms[form_idx].addEventListener('submit', parseForm, false);" +  
     "var inputs = document.getElementsByTagName('input');" + 
     "for (var i = 0; i < inputs.length; i++) {" + 
     " if (inputs[i].getAttribute('type') == 'button')" + 
     "  inputs[i].addEventListener('click', parseForm, false);" + 
     "}" + 
     ""; 

    class JavaScriptInterface { 
     @JavascriptInterface 
     public void processFormData(String formData) { 
      //added annotation for API > 17 to make it work 
      <do whatever you need to do with the form data> 
     } 
    } 

    onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.browser); 
     WebView browser = (WebView)findViewById(R.id.browser_window); 
     browser.getSettings().setJavaScriptEnabled(true); 
     browser.addJavascriptInterface(new JavaScriptInterface(), "HTMLOUT"); 
     browser.setWebViewClient(new WebViewClient() { 
     @Override 
     public boolean shouldOverrideUrlLoading(WebView view, String url) { 
      view.loadUrl(url); 
      return true; 
     } 

     @Override 
     public void onPageFinished(WebView view, String url) { 
      view.loadUrl("javascript:(function() { " + 
         MyBrowser.jsInjectCode + "})()"); 
     } 
} 

chính thức, điều này không là tiêm các tùy chỉnh mã JavaScript (như một handler onsubmit) bất cứ khi nào một trang kết thúc tải. Khi gửi biểu mẫu, Javascript sẽ phân tích cú pháp dữ liệu biểu mẫu và chuyển nó trở lại vùng đất Java thông qua đối tượng JavaScriptInterface.

Để phân tích các trường biểu mẫu, mã Javascript thêm biểu mẫu onsubmit và nút xử lý onclick. Trước đây, người dùng có thể xử lý việc gửi biểu mẫu chuẩn thông qua nút gửi thông thường trong khi giao dịch sau có nút gửi tùy chỉnh, tức là các nút thực hiện thêm một số phép thuật Javascript trước khi gọi form.submit().

Xin lưu ý rằng mã Javascript có thể không hoàn hảo: Có thể có các phương pháp khác để gửi biểu mẫu mà mã được tiêm của tôi có thể không bắt được. Tuy nhiên, tôi tin rằng mã tiêm có thể được cập nhật để đối phó với các khả năng như vậy.

+0

'window.HTMLOUT.processFormData (dữ liệu);' không hoạt động đối với tôi, nhưng chỉ 'HTMLOUT.processFormData (dữ liệu);' đã làm việc cho tôi. – flexdroid

+0

đẹp .... cảm ơn người đàn ông – Noman

+0

ok, tôi finnaly đã nhận nó. sửa chữa mã cũng –

6

Câu trả lời được cung cấp cho lỗi vì vậy tôi quyết định làm một việc thực hiện đơn giản hơn mà cũng đặc trưng cấu trúc cũng JavaScript (JS nghĩa là trong một tập tin):

Trong tài sản của bạn thư mục tạo ra một tập tin gọi là inject.js với đoạn mã sau bên trong:

document.getElementsByTagName('form')[0].onsubmit = function() { 
    var objPWD, objAccount, objSave; 
    var str = ''; 
    var inputs = document.getElementsByTagName('input'); 
    for (var i = 0; i < inputs.length; i++) { 
     if (inputs[i].name.toLowerCase() === 'username') { 
      objAccount = inputs[i]; 
     } else if (inputs[i].name.toLowerCase() === 'password') { 
      objPWD = inputs[i]; 
     } else if (inputs[i].name.toLowerCase() === 'rememberlogin') { 
      objSave = inputs[i]; 
     } 
    } 
    if(objAccount != null) { 
     str += objAccount.value; 
    } 
    if(objPWD != null) { 
     str += ' , ' + objPWD.value; 
    } 
    if(objSave != null) { 
     str += ' , ' + objSave.value; 
    } 
    window.AndroidInterface.processHTML(str); 
    return true; 
}; 

Đây là mã javascript chúng tôi sẽ sử dụng để tiêm, bạn có thể chuyển đổi câu lệnh nếu bạn thấy phù hợp và sử dụng loại thay thế hoặc tên.Gọi lại cho Android là dòng này: window.AndroidInterface.processHTML(str);

Sau đó, hoạt động của bạn/mảnh nên trông như thế này:

public class MainActivity extends ActionBarActivity { 
    class JavaScriptInterface { 
     @JavascriptInterface 
     public void processHTML(String formData) { 
      Log.d("AWESOME_TAG", "form data: " + formData); 
     } 
    } 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     WebView webView = new WebView(this); 
     this.setContentView(webView); 

     // enable javascript 
     WebSettings webSettings = webView.getSettings(); 
     webSettings.setJavaScriptEnabled(true); 
     webView.addJavascriptInterface(new JavaScriptInterface(), "AndroidInterface"); 

     // catch events 
     webView.setWebViewClient(new WebViewClient(){ 
      @Override 
      public void onPageFinished(WebView view, String url) { 
       try { 
        view.loadUrl("javascript:" + buildInjection()); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 

     webView.loadUrl("http://someurl.com"); 
    } 

    private String buildInjection() throws IOException { 
     StringBuilder buf = new StringBuilder(); 
     InputStream inject = getAssets().open("inject.js");// file from assets 
     BufferedReader in = new BufferedReader(new InputStreamReader(inject, "UTF-8")); 
     String str; 
     while ((str = in.readLine()) != null) { 
      buf.append(str); 
     } 
     in.close(); 

     return buf.toString(); 
    } 
+0

Nơi nào bạn nhận được giá trị từ hộp nhập liệu –

Các vấn đề liên quan