android जावास्क्रिप्ट का मूल्यांकन कैसे करता है?




android-webview android-4.4-kitkat (4)

मैं एंड्रॉइड 4.4 में नए evaluateJavascript विधि evaluateJavascript उपयोग करने की कोशिश कर रहा हूं, लेकिन जो भी मैंने कभी वापस प्राप्त किया है वह एक शून्य परिणाम है:

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

मैं इस विधि के परिणाम कैसे वापस कर सकता हूं?

अद्यतन: थोड़ा और जानकारी:

  1. मेरे पास इंटरनेट अनुमति सेट है
  2. मैंने setJavascriptEnabled(true);
  3. एस्ट्रोफ़े स्ट्रिंग का प्रयास किया: return 'test'; ,
  4. जेएस ऑब्जेक्ट का प्रयास किया: return { test: 'this' }
  5. console.log('test'); ठीक से निष्पादित किया जा रहा है।
  6. targetSdkVersion अनुसार targetSdkVersion को सेट करें: यदि आपका ऐप WebView का उपयोग करता है

डिवाइस: नेक्सस 7 और नेक्सस 5 (स्टॉक) दोनों


इस नमूने में मूल्यांकन जावास्क्रिप्ट विधि का उपयोग करने का एक उदाहरण है:

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

अनिवार्य रूप से यदि वेबव्यू में आपके द्वारा निष्पादित जावास्क्रिप्ट एक मान देता है तो यह कॉलबैक में पारित किया जाएगा।

ध्यान देने योग्य मुख्य बात यह है कि ऑनरिसिव वैल्यू में लौटाई गई स्ट्रिंग या तो आप जो भी लौटते हैं उसके आधार पर JSON मान, JSON ऑब्जेक्ट या JSON Array है।

इसके बारे में ध्यान देने योग्य चीजें यह है कि यदि आप एक एकल मान वापस करते हैं, तो आपको काम करने के लिए JSON रीडर पर सेटलेनेंट (सत्य) का उपयोग करने की आवश्यकता है।

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

एक स्ट्रिंग प्रतिक्रिया के लिए आप अभी भी एक पार्सर का उपयोग करना चाहते हैं, यह एक JSON मान में परिवर्तित हो गया है जिसका अर्थ है कि इसे उद्धरणों में लपेटा जाएगा।

उदाहरण के लिए यदि आप गए:

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

यह स्ट्रिंग को प्रिंट करेगा, डबल कोट्स में लपेटा जाएगा: "यह"।

ध्यान देने योग्य अन्य उदाहरण:

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

@ गौंटफेस के उत्तर को सारांशित करने के लिए और JSON पार्सर का उपयोग किये बिना वैकल्पिक समाधान प्रदान करें:

यदि आपका जेएस फ़ंक्शन केवल एक String और आप इस बारे में सोच रहे हैं कि जावा में स्ट्रिंग क्यों उलझाई गई है, तो ऐसा इसलिए है क्योंकि यह JSON-escaped है।

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

(ध्यान दें कि onReceiveValue हमेशा एक String प्रदान करता है जबकि जेएस फ़ंक्शन एक null , संख्या String आदि लौटा सकता है)

स्ट्रिंग मान को जेएस में समान करने के लिए, यदि आप 100% सुनिश्चित हैं कि आप उचित String लौटने की उम्मीद कर रहे हैं, तो आपको JSON-unescape की आवश्यकता होगी, उदाहरण के लिए:

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

हालांकि, ध्यान दें कि एसएस एक स्ट्रिंग "null" हो सकता है यदि जेएस उचित null देता है, तो आपको स्पष्ट रूप से इसे पहले चरण के रूप में जांचना होगा।

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

AndroidJSCore जावास्क्रिप्ट का मूल्यांकन करने के लिए एक अच्छा विकल्प है जो वेबव्यू का उपयोग नहीं करता है।

यदि आप वेब व्यू के साथ रहना चाहते हैं और एंड्रॉइड (4+) के पुराने संस्करणों पर जावास्क्रिप्ट का मूल्यांकन करने की आवश्यकता है, तो यहां एक छोटी लाइब्रेरी है:

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

ठीक है, तो यह result दिखाता है कि परिणाम जावास्क्रिप्ट कॉल का परिणाम है - जैसे कि कोई जावास्क्रिप्ट कंसोल में कमांड दर्ज कर रहा था।

तो परिणाम प्राप्त करने के लिए, इसे किसी फ़ंक्शन में लपेटने की आवश्यकता है:

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

यह भी काम करेगा:

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

विधि जावास्क्रिप्ट ऑब्जेक्ट्स को भी संभालती है:

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




android-4.4-kitkat