Bagaimana evaluateJavascript bekerja?

I'm mencoba untuk menggunakan yang baru evaluateJavascript metode di Android 4.4, tapi semua yang pernah saya dapatkan kembali adalah null hasilnya:

webView1.evaluateJavascript("return \"test\";", new ValueCallback<String>() {
    @Override
    public void onReceiveValue(String s) {
        Log.d("LogName", s); // Log is written, but s is always null
    }
});

Bagaimana saya mengembalikan hasil untuk metode ini?

Update: Sedikit info lebih lanjut:

  1. Aku memiliki izin INTERNET set
  2. Saya memiliki setJavascriptEnabled(true);
  3. Mencoba apostrophe string: kembali &#39;test&#39;;,
  4. Mencoba JS objek: kembali { tes: &#39;ini&#39; }
  5. konsol.log(&#39;test&#39;); sedang dijalankan baik-baik saja.
  6. Set targetSdkVersion ke 19 sebagai per: Jika aplikasi anda menggunakan WebView

Perangkat: Kedua Nexus 7 dan Nexus 5 (Saham)

Larutan

Ada contoh evaluateJavascript metode yang digunakan dalam contoh ini:

https://github.com/GoogleChrome/chromium-webview-samples/tree/master/jsinterface-example

Pada dasarnya jika javascript anda jalankan di WebView mengembalikan nilai itu'akan berlalu di balik.

Hal utama yang perlu diperhatikan adalah bahwa String yang dikembalikan dalam OnReceiveValue adalah berupa JSON Nilai, Objek JSON atau JSON Array tergantung pada apa yang anda kembali.

Hal-hal yang perlu diperhatikan tentang hal ini jika anda mengembalikan nilai tunggal, anda perlu menggunakan setLenient(benar) pada JSON reader untuk itu untuk bekerja.

     if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        // In KitKat+ you should use the evaluateJavascript method
        mWebView.evaluateJavascript(javascript, new ValueCallback() {
            @TargetApi(Build.VERSION_CODES.HONEYCOMB)
            @Override
            public void onReceiveValue(String s) {
                JsonReader reader = new JsonReader(new StringReader(s));

                // Must set lenient to parse single values
                reader.setLenient(true);

                try {
                    if(reader.peek() != JsonToken.NULL) {
                        if(reader.peek() == JsonToken.STRING) {
                            String msg = reader.nextString();
                            if(msg != null) {
                                Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
                            }
                        }
                    }
                } catch (IOException e) {
                    Log.e("TAG", "MainActivity: IOException", e);
                } finally {
                    try {
                        reader.close();
                    } catch (IOException e) {
                        // NOOP
                    }
                }
            }
        });
    }

Alasan anda mungkin masih ingin menggunakan parser untuk string respon itu dikonversi ke JSON nilai yang berarti itu akan dibungkus dalam tanda kutip.

Misalnya jika anda pergi:

mWebView.evaluateJavascript("(function() { return 'this'; })();", new ValueCallback() {
    @Override
    public void onReceiveValue(String s) {
        Log.d("LogName", s); // Prints: "this"
    }
});

Ini akan mencetak string ini, dibungkus dengan tanda kutip ganda: "ini".

Contoh lain yang patut dicatat:

mWebView.evaluateJavascript("(function() { return null; })();", new ValueCallback() {
    @Override
    public void onReceiveValue(String s) {
        Log.d("LogName", s); // Prints the string 'null' NOT Java null
    }
});

mWebView.evaluateJavascript("(function() { })();", new ValueCallback() {
    @Override
    public void onReceiveValue(String s) {
        Log.d("LogName", s); //s is Java null
    }
});

mWebView.evaluateJavascript("(function() { return ''; })();", new ValueCallback() {
    @Override
    public void onReceiveValue(String s) {
        Log.d("LogName", s); // Prints "" (Two double quotes)
    }
});
Komentar (5)

OK, jadi ternyata hasil di sini adalah hasil dari Javascript panggilan - seperti jika seseorang memasukkan perintah ke dalam konsol Javascript.

Jadi dalam rangka untuk mendapatkan hasil, itu harus dibungkus dalam sebuah fungsi:

webView1.evaluateJavascript("(function() { return \"this\"; })();", new ValueCallback() {
    @Override
    public void onReceiveValue(String s) {
        Log.d("LogName", s); // Prints 'this'
    }
});

Ini juga akan bekerja:

webView1.evaluateJavascript("window.variable = \"asd\";", new ValueCallback() {
    @Override
    public void onReceiveValue(String s) {
        Log.d("LogName", s); // Prints asd
    }
});

Metode ini juga menangani objek Javascript:

webView1.evaluateJavascript("(function() { return { var1: \"variable1\", var2: \"variable2\" }; })();", new ValueCallback() {
    @Override
    public void onReceiveValue(String s) {
        Log.d("LogName", s); // Prints: {"var1":"variable1","var2":"variable2"}
    }
});
Komentar (0)

AndroidJSCore adalah alternatif yang baik untuk mengevaluasi JavaScript yang tidak menggunakan WebView.

Jika anda ingin tetap dengan WebView dan perlu untuk mengevaluasi JavaScript pada versi sebelumnya (Android 4+), berikut adalah sedikit perpustakaan:

https://github.com/evgenyneu/js-evaluator-for-android

jsEvaluator.evaluate("put your JavaScript code", new JsCallback() {
  @Override
  public void onResult(final String result) {
    // get result here (optional)
  }
});
Komentar (2)

Untuk meringkas jawaban dari @GauntFace dan memberikan alternatif solusi tanpa menggunakan JSON parser:

Jika anda JS kembali fungsi hanya String dan're-tanya tentang mengapa string hancur di pulau Jawa, it's karena itu's JSON-lolos.

mWebView.evaluateJavascript("(function() { return 'Earvin \"Magic\" Johnson'; })();", new ValueCallback() {
    @Override
    public void onReceiveValue(String s) {
        Log.d("LogName", s);
        // expected: s == Earvin "Magic" Johnson
        // actual:   s == "Earvin \"Magic\" Johnson"
    }
});

(perhatikan bahwa onReceiveValue menyediakan String sementara JS fungsi dapat mengembalikan null, Sejumlah literal dll.)

Untuk mendapatkan nilai string yang sama seperti di JS, jika anda'kembali 100% yakin anda're mengharapkan tepat String kembali, kau'd perlu JSON-unescape itu, misalnya seperti:

String unescaped = s.substring(1, s.length() - 1)  // remove wrapping quotes
                     .replace("\\\\", "\\")        // unescape \\ -> \
                     .replace("\\\"", "\"");       // unescape \" -> "

Namun, perhatikan bahwa s mungkin string "null" jika JS kembali tepat null, jadi anda jelas perlu memeriksa bahwa sebagai langkah pertama.

if ("null".equals(s)) {
   ...
} else {
   // unescape JSON
}
Komentar (0)

Semua orang's jawaban yang lebih besar. Saya hanya menambahkan satu poin lagi. Don't menempatkan evaluateJavascript dalam metode dengan @JavascripInterface penjelasan seperti ini cara @JavascripInterface public void onData(){ mWebView.evaluateJavascript("javascript:executeNext()",null); } Karena itu akan memblokir JavaBridge Benang. jika anda ingin menempatkan evaluateJavascript di dalamnya. Melakukannya dengan cara ini `` @JavascripInterface public void onData(){ mWebView.posting(new Runnable() { @Override public void run() { mWebView.evaluateJavascript("javascript:executeNext()",null); } });

} ``

Komentar (0)