web-dev-qa-db-ja.com

webViewの使用中に、HTMLフォームからAndroidにデータを取得することは可能ですか?

Androidで表示されるHTMLで非常にシンプルなフォームを作成しています。テキストボックスを使用して名前を取得し、ボタンをクリックすると段落に表示されます。 htmlとjavascriptの両方を使用して作成されています。これは私のhtmlコードです。

<!DOCTYPE html>
<html>
<body>
<p> Write your name and win your favorite game console name and win it! The winners will be announced in 4 days.</p>
Type your name here: <input id="thebox" type="text" name="value" value=""><br>

    <button onclick="myFunction()">Try it</button>

    <p id="demo"></p>

    <script>
    function myFunction() {
        var x = document.getElementById("thebox").value;
        document.getElementById("demo").innerHTML = x;
    }
    </script>

    </body>
    </html>

新しい編集フォーム

<form name="albert" action="" method="POST">

 <label for="firstname"> First Name </label>
 <br /><br />

 <input type="text" name="firstname" id="firstname" />

 <input type="submit" name="sbumit" value="Submit" />


</form>

私はAndroidボタンクリックで変数の "thebox"と呼ばれる入力ボックスから値を取得したいのですが、前にたくさんのことを試し、JSファイルを注入する方法に従いましたしかし、私はJSについて何も知らないので、それを試して失敗しました。ここに私のプロジェクトに入れたファイルがあり、ファイルはinject.jsと呼ばれます:

document.getElementsByTagName('form')[0].onsubmit = function () {
    var objPWD, objAccount, objSave;
    var str = '';
    var inputs = document.getElementsByTagName('thebox');
    for (var i = 0; i < inputs.length; i++) {
        if (inputs[i].name.toLowerCase() === 'thebox') {
            objAccount = 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;
};

後でその記事を読んだときに、MainActivityに何かを入れる必要があると言われましたが、初めてWebViewを使用しているので、MainActivityに入れたコードをあまり理解できませんでした。

 @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");
    }

MainActivityで作成したネストされたクラス:

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

そして最後に、コードを注入するメソッド:

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();
    }

Androidでウェブビューに表示するhtmlフォーム(the-input-box)から値を取得したいのですが、実際にそれを行うことはできますか?また、値を取得する変数を教えてください。

19
Shariq Musharaf
    Webview browser=(WebView)view.findViewById(R.id.webChart);
    browser.getSettings().setJavaScriptEnabled(true);
    browser.addJavascriptInterface(new WebAppInterface(getActivity()), "Android");
    browser.loadUrl("file:///Android_asset/yourHtmlFileName.html");

このインターフェイスクラスWebAppInterfaceを追加します

public class WebAppInterface {
 Context mContext;
 String data;

 WebAppInterface(Context ctx){
    this.mContext=ctx;
 } 


 @JavascriptInterface
 public void sendData(String data) {
    //Get the string value to process
      this.data=data;
 }
}

hTMLコードデータ

 function loadChartData() {
  var x = document.getElementById("thebox").value;
   Android.sendData(x);
 }

htmlボタンがクリックされたときにこの関数を呼び出すAndroid webview

[〜#〜] update [〜#〜]

1)デフォルトでは、javascriptはwebviewで無効になっています。有効にするには、webviewの設定を取得し、setJavaScriptEnabled(true)を呼び出します。本当に。

2)JavascriptコードとAndroidコードの間にインターフェイスを作成するには、Javacriptインターフェイスクラスを作成する必要があります。

3)JavaScriptコード間のインターフェイスをAndroidコードにバインドします。インターフェイスクラスの参照を渡す必要がありますそして、javaScriptがクラスにアクセスするために呼び出すことができるインターフェース名。

4)htmlファイルパスを渡してwebview(browser)にロードします。

5)以下のようなインターフェイスクラスを作成します(WebAppInterface)。

詳細については、このリンクを参照してください https://developer.Android.com/guide/webapps/webview.html

6)HTMLファイルでボタンを作成し、そのボタンにクリックリスナーを追加し、sendData( "your value")関数をインターフェイス名(ここではAndroid)。

それで全部です。値をhtmlからAndroidコードに渡すことができます。

20
Noorul

はい、できます。javascriptを使用してWebページのコンテンツを取得できます。次に、webview jsInterfaceを使用してコンテンツを返しますJavaコード。

これを参照してください githubプロジェクト 。そして、この answer およびこの article

final Context myApp = this;

/* An instance of this class will be registered as a JavaScript interface */
class MyJavaScriptInterface
{
    @JavascriptInterface
    @SuppressWarnings("unused")
    public void processHTML(String html)
    {
        // process the html as needed by the app
    }
}

final WebView browser = (WebView)findViewById(R.id.browser);
/* JavaScript must be enabled if you want it to work, obviously */
browser.getSettings().setJavaScriptEnabled(true);

/* Register a new JavaScript interface called HTMLOUT */
browser.addJavascriptInterface(new MyJavaScriptInterface(), "HTMLOUT");

/* WebViewClient must be set BEFORE calling loadUrl! */
browser.setWebViewClient(new WebViewClient() {
    @Override
    public void onPageFinished(WebView view, String url)
    {
        /* This call inject JavaScript into the page which just finished loading. */
        browser.loadUrl("javascript:window.HTMLOUT.processHTML('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");
    }
});

/* load a web page */
browser.loadUrl("http://lexandera.com/files/jsexamples/gethtml.html");

お役に立てれば。

5
Kris Roofe

メソッド「GET」を持つフォームの場合、shouldOverrideUrlLoadingメソッドをオーバーライドするだけで、これを非常に簡単に実現できます。次の解決策は、URLがwebview.loadUrl()メソッドを介してロードされた場合にのみ機能します。

private class MWebViewClient extends WebViewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) { 
        // submit will end-up with url like "data:,?firstname=SomeInput&sbumit=Submit"
        if (URLUtil.isDataUrl(url)) {
            url = url.replace(":,?", ":/?"); //to be able to properly parse Uri
            Uri uri = Uri.parse(url);

            //here you can get params by field name 
            String firstname = uri.getQueryParameter("firstname");

            //we handle this URL ourselves 
            return true;
        }

        return super.shouldOverrideUrlLoading(view, url);
    }
}
3
j2ko

WebViewをネイティブAndroidと通信するには、これは簡単な方法です。jsonClickボタンで、myPrefix:// myDataのようなテキストを含むurlを呼び出す必要があります。

webView.setWebViewClient(new WebViewClient()
{
   @Override
   public boolean shouldOverrideUrlLoading(final WebView view, final String url) 
    {
     if(url.startsWith("myPrefix://")) 
      {
       //get your data by split url
       return true;
      }
 return false;

});
2
Ahmed.ess

@Shariq多くの人がすでにこの質問に良い方法で答えていますが、さらに、webviewからandoridへのコードへのデータの流れを明確にする必要があるので、すべての冗長コードを書くのにバイトを浪費しません:

(理解を深めるためにコードを参照しています)これらのコードの以下の手順に従って、理解を深めてください。

ステップ1:

Android Webviewからのデータを受け入れることができる側でメソッドを定義する必要があります

@JavascriptInterface
//this 'formData' variable is going to accept the data from webview 
public void processHTML(String formData) {
    Log.d("AWESOME_TAG", "form data: " + formData);
}

これで、その値はJava Android side context。

ステップ2:

これがHTMLサイドコード(webview)です。 WebViewでアクセスしているURLがあなたのものである場合、これらのコードを簡単にhtmlページに書き込むことができますが、サードパーティのURLにアクセスしている場合は、次のコード行でこのjsコードをwebviewに挿入できます:

...
//partial code
webView.load("javascript:function myFunction() { var x = document.getElementById('thebox').value; Android.processHTML(x); } myFunction();";
... 

ここで正確に何が起こっているのか:

「x」は必要な値を保持するjsの変数であり、この「x」変数をAndroidメソッド呼び出し経由でコンテキストに送信していますAndroid.processHTML(x)

より良い方法であなたに役立つことを願っています

はい、可能です。以下のコードを使用してみてください

>  @Override
>     public void onCreate(Bundle savedInstanceState) {
>         super.onCreate(savedInstanceState);
>         setContentView(R.layout.web_view_layout);
>         WebView webView = (WebView) findViewById(R.id.webView);
>         webView.getSettings().setPluginState(WebSettings.PluginState.ON);
>         WebSettings webSettings = webView.getSettings();
>         webSettings.setJavaScriptEnabled(true);
>         try {
>             progressDialog = new ProgressDialog(ActivityName);
>         progressDialog.setMessage("Loading.."); progressDialog.setCancelable(false);
>             webView.setWebViewClient(new MyWebViewClient());
>             webView.loadUrl(YOUR_URL);
>         } catch (Exception e) {
>             e.toString();
>         }
>     }
> 
>     private class MyWebViewClient extends WebViewClient {
> 
>         @Override
>         public boolean shouldOverrideUrlLoading(WebView view, String url) {
>             view.loadUrl(url);
>            progressDialog.dismissProgress();
>             return true;
>         }
> 
>         @Override
>         public void onPageFinished(WebView view, String url) {
>             progressDialog.dismissProgress();
>         }
>     }
2

警告メッセージをキャッチすることにより、WebViewからデータを取得できます。

WebChromeClientを使用します。

mWebview = (WebView)findViewById(R.id.yourwebviewlayout);
final class YourWebChromeClient extends WebChromeClient {
                @Override
                public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                    Toast.makeText(getApplicationContext(),
                            "alert message =  " + message,
                            Toast.LENGTH_SHORT).show();
                    result.confirm();
                    return true;
                }
            }
mWebview.setWebChromeClient(new YourWebChromeClient());
1
Rainmaker

これまでに注入するのに最適なjsは、送信時にすべてのフォームからデータを収集します。

document.getElementsByTagName("form")[0].addEventListener("submit", myFunction);
function myFunction()
{
    var data="";
    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+'\n';
    }
    window.AndroidInterface.processHTML(data);
    return true;
}
0
Sikini Joseph