it-swarm.com.de

Wie funktioniert JavaScript?

Ich versuche, die neue evaluationJavascript -Methode in Android 4.4 zu verwenden, aber alles, was ich jemals zurück bekomme, ist ein Null-Ergebnis:

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

Wie gebe ich ein Ergebnis für diese Methode zurück?

Update: Ein bisschen mehr Info:

  1. Ich habe die INTERNET-Berechtigung festgelegt
  2. Ich habe setJavascriptEnabled(true);
  3. Versuchte Apostrophzeichenfolge: return 'test';,
  4. Versuchtes JS-Objekt: return { test: 'this' }
  5. console.log('test'); wird einwandfrei ausgeführt.
  6. Setzen Sie targetSdkVersion wie folgt auf 19: Wenn Ihre App WebView verwendet

Geräte: Sowohl Nexus 7 als auch Nexus 5 (Lager)

42
CodingIntrigue

In diesem Beispiel wird ein Beispiel für die evaluJavascript-Methode verwendet:

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

Wenn das in der WebView ausgeführte Javascript einen Wert zurückgibt, wird es im Callback übergeben.

Beachten Sie vor allem, dass der in OnReceiveValue zurückgegebene String je nach Ergebnis entweder ein JSON-Wert, ein JSON-Objekt oder ein JSON-Array ist.

Zu beachten ist hierbei Folgendes: Wenn Sie einen einzelnen Wert zurückgeben, müssen Sie setLenient (true) für einen JSON-Reader verwenden, damit er funktioniert.

     if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KitKat) {
        // In KitKat+ you should use the evaluateJavascript method
        mWebView.evaluateJavascript(javascript, new ValueCallback<String>() {
            @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
                    }
                }
            }
        });
    }

Möglicherweise möchten Sie einen Parser für eine Zeichenfolgenantwort verwenden, weil er in einen JSON-Wert konvertiert wird. Dies bedeutet, dass er in Anführungszeichen gesetzt wird.

Zum Beispiel, wenn Sie gegangen sind:

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

Die Zeichenfolge würde in doppelten Anführungszeichen ausgegeben: "this".

Weitere erwähnenswerte Beispiele:

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

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

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

OK, es stellt sich also heraus, dass die Variable result hier das Ergebnis des Javascript-Aufrufs ist - als würde man den Befehl in eine Javascript-Konsole eingeben.

Um ein Ergebnis zu erhalten, muss es in eine Funktion eingeschlossen werden:

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

Das wird auch funktionieren:

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

Die Methode behandelt auch Javascript-Objekte:

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

AndroidJSCore ist eine gute Alternative zur Bewertung von JavaScript, das kein WebView verwendet.

Wenn Sie bei WebView bleiben möchten und JavaScript in früheren Versionen von Android (4+) bewerten müssen, finden Sie hier eine kleine Bibliothek:

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

Um die Antwort von @GauntFace zusammenzufassen und eine alternative Lösung ohne JSON-Parser bereitzustellen:

Wenn Ihre JS-Funktion nur eine String zurückgibt und Sie sich fragen, warum die Zeichenfolge in Java beschädigt ist, liegt dies daran, dass es sich um einen JSON-Code handelt.

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

(Beachten Sie, dass onReceiveValue immer eine String bereitstellt, während die JS-Funktion eine null, ein Number-Literal usw. zurückgeben kann.)

Um den String-Wert wie in JS zu erhalten, müssen Sie, wenn Sie zu 100% sicher sind, dass Sie eine korrekte String zurückgeben, JSON-unescape verwenden, z.

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

Beachten Sie jedoch, dass s eine Zeichenfolge "null" sein kann, wenn JS die richtige null zurückgibt. Sie müssen dies natürlich als ersten Schritt überprüfen.

if ("null".equals(s)) {
   ...
} else {
   // unescape JSON
}
2
jakub.g

Die Antwort von allen ist großartig. Ich füge nur noch einen Punkt hinzu. Fügen Sie mit der @JavascripInterface-Annotation wie folgt keine evaluJavascript-Methode in die Methode ein

    @JavascripInterface
    public void onData(){ 
            mWebView.evaluateJavascript("javascript:executeNext()",null);
    }  

Dadurch wird der JavaBridge-Thread . Blockiert, wenn JavaScript zum Auswerten von JavaScript verwendet werden soll. Mach es auf diese Weise

    @JavascripInterface
    public void onData(){
        mWebView.post(new Runnable() {
            @Override
            public void run() {
                mWebView.evaluateJavascript("javascript:executeNext()",null);
            }
        });

    }
1
littlebear333