WebView में Android कॉलिंग जावास्क्रिप्ट फ़ंक्शंस


249

मैं अंदर चल रहे पृष्ठ javascriptमें बैठे कुछ फ़ंक्शन को कॉल करने का प्रयास कर रहा हूं । एंड्रॉइड ऐप से कोड को नीचे करने की कोशिश करने में बहुत सरल है - एक परीक्षण संदेश के साथ एक फ़ंक्शन को कॉल करें , जो टोस्ट के माध्यम से परीक्षण संदेश प्रदर्शित करने वाले एंड्रॉइड ऐप में एक जावा फ़ंक्शन को वापस कॉल करता है।htmlandroid webviewjavascript

javascriptसमारोह लगता है कि:

function testEcho(message){
     window.JSInterface.doEchoTest(message);
}

WebView से, मैंने javascriptनिम्नलिखित तरीकों को बिना किसी भाग्य के कॉल करने की कोशिश की है :

myWebView.loadUrl("javascript:testEcho(Hello World!)");
mWebView.loadUrl("javascript:(function () { " + "testEcho(Hello World!);" + "})()");

मैंने सक्षम javascriptकियाWebView

myWebView.getSettings().setJavaScriptEnabled(true);
// register class containing methods to be exposed to JavaScript
myWebView.addJavascriptInterface(myJSInterface, "JSInterface"); 

और विधर्मियों का Javaवर्ग

public class JSInterface{

private WebView mAppView;
public JSInterface  (WebView appView) {
        this.mAppView = appView;
    }

    public void doEchoTest(String echo){
        Toast toast = Toast.makeText(mAppView.getContext(), echo, Toast.LENGTH_SHORT);
        toast.show();
    }
}

मैंने यह देखने के लिए बहुत समय बिताया है कि मैं क्या गलत कर सकता हूं। सभी उदाहरण मैंने पाया है कि इस दृष्टिकोण का उपयोग करें। क्या किसी को यहाँ कुछ गलत दिखाई देता है?

संपादित करें: कई अन्य बाहरी javascriptफाइलें संदर्भित या उपयोग की जा रही हैं html, क्या वे समस्या हो सकती हैं?


13
आप जिस कोड का उपयोग करने की कोशिश करते हैं, वह जावास्क्रिप्ट साइड पर उद्धरणों को याद करता है।
पॉल डे वीरेज़

2
कृपया ध्यान दें कि एंड्रॉइड 4.2 के बाद से आपको @JavascriptInterfaceजावा विधियों पर डेकोरेटर का उपयोग करना होगा जिसे आप जावास्क्रिप्ट इंटरफ़ेस के माध्यम से वेब व्यू को उपलब्ध कराना चाहते हैं।
फ्रेड

1
कोड से myWebView.loadUrl("javascript:testEcho('Hello World!')");मैं समझता हूं कि आपने पहले ही html फाइल को उस वेबव्यू में संलग्न कर लिया है। क्या आप मुझे बता सकते हैं कि आपने ऐसा कैसे किया?
टोनी_क्राफ्ट

जवाबों:


195

मुझे पता चला कि मुद्दा क्या था: टेस्टचो () पैरामीटर में गायब उद्धरण। इस तरह मुझे काम करने के लिए कॉल मिला:

myWebView.loadUrl("javascript:testEcho('Hello World!')");

कृपया इन लिंक में एक नज़र है stackoverflow.com/questions/9079374/…
kamal_tech_view

यह अच्छा है, लेकिन आप जावा ऑब्जेक्ट पर जावास्क्रिप्ट फ़ंक्शन के तर्क के रूप में कैसे पास करते हैं?
कोव्स इमर्रे

1
@ KovácsImre String.Format ("javascript: testEcho ('% d', '% d', '% d')", 1, 2, 3); मुझे लगता है
user457015

धन्यवाद, मैं भी इस बीच में पता चला है।
कोवेक इमर्रे

1
किटकैट से शुरू होने वाली मूल्यांकन
जावास्क्रिप्ट

117

किटकैट से बाद में मूल्यांकन जावास्क्रिप्ट विधि का उपयोग करें, इसके बजाय नीचे दिए गए जावास्क्रिप्ट कार्यों को कॉल करने के लिए लोड करें

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
        webView.evaluateJavascript("enable();", null);
    } else {
        webView.loadUrl("javascript:enable();");
    }

2
क्यों लोडयूआरएल () के बजाय मूल्यांकनजैस्क्रिप्ट () का उपयोग करें?
कामरान बिगली

2
@kami loadUrl () पेज को फिर से लोड करेगा और onPageFinished () को फिर से कॉल करेगा
Zach

1
@Zach यह अभी भी प्री-किटकैट पर एक मुद्दा है, है ना?
Vsevolod Ganin

2
@kami Zach जवाब में जोड़कर, मूल्यांकन जावास्क्रिप्ट (), जावास्क्रिप्ट को अतुल्यकालिक रूप से चलाएगा। इसलिए हम मूल्यांकन जावास्क्रिप्ट () का उपयोग करके यूआई थ्रेड को अवरुद्ध करने से बच सकते हैं।
प्रसाद

loadUrlजब मैंने इनपुट फ़ील्ड में मान भरने का प्रयास किया तो सॉफ्टवेयर कीबोर्ड भी दिखाई दिया।
जोशुआ

34
public void run(final String scriptSrc) { 
        webView.post(new Runnable() {
            @Override
            public void run() { 
                webView.loadUrl("javascript:" + scriptSrc); 
            }
        }); 
    }

। और अगर यह नहीं काम करता है, नए थ्रेड करना (नए Runnaable () {.. <ऊपर की तरह> ..}) शुरू ()
राडू Simionescu

26

मैंने जावास्क्रिप्ट विधियों को कॉल करने के लिए एक अच्छा आवरण बनाया; यह लॉग में जावास्क्रिप्ट त्रुटियों को भी दिखाता है:

private void callJavaScript(String methodName, Object...params){
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append("javascript:try{");
    stringBuilder.append(methodName);
    stringBuilder.append("(");
    for (int i = 0; i < params.length; i++) {
        Object param = params[i];
        if(param instanceof String){
            stringBuilder.append("'");
            stringBuilder.append(param.toString().replace("'", "\\'"));
            stringBuilder.append("'");
        }
        if(i < params.length - 1){
            stringBuilder.append(",");
        }
    }
    stringBuilder.append(")}catch(error){Android.onError(error.message);}");
    webView.loadUrl(stringBuilder.toString());
}

आपको इसे भी जोड़ना होगा:

private class WebViewInterface{

    @JavascriptInterface
    public void onError(String error){
        throw new Error(error);
    }
}

और इस इंटरफ़ेस को अपने वेबव्यू में जोड़ें:

webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new WebViewInterface(), "AndroidErrorReporter");

यह फ़ंक्शन, हालांकि एक विचार के रूप में अच्छा है, गलत कार्यान्वयन है। इस कॉल: final Object a = new Object(); callJavaScript(mBrowser, "alert", 1, true, "abc", a);करने के लिए निकलेगा SyntaxErrorसाथ Unexpected tokenजो आश्चर्य की बात नहीं है जब आप उत्पन्न js पर नजर डालेंगे फोन:javascript:try{alert(,,'abc',,)}catch(error){console.error(error.message);}
लुकाज़ 'Severiaan' Grela

यहां तक ​​कि सरल कॉल callJavaScript(mBrowser, "alert", "abc", "def");त्रुटि उत्पन्न करता है क्योंकि अंत में हमेशा दुष्ट अल्पविराम होता है। -1 मुझसे।
लुकाज़ 'सेवरियान' ग्रीला

1
@ Lukasz'Severiaan'Grela tnx, मैंने यह तय किया। PS अगली बार आलसी मत बनो आप इसे खुद ठीक कर सकते हैं ...;)
इल्या गज़मैन

16
भविष्य के संदर्भ के लिए: आइए सकारात्मक रहें। कोड में कोई त्रुटि इंगित करना आलसी नहीं है। यह अभी भी उपयोगी प्रतिक्रिया है।
डीडब्ल्यू

मुझे लगता है कि यह काम नहीं करेगा अगर किसी भी पैरामीटर का चरित्र इसमें है? उदाहरण:callJavascript(mBrowser, "can't do it");
Kostanos

18

हाँ, आपको सिंटैक्स त्रुटि है। यदि आप अपने जावास्क्रिप्ट त्रुटियों और मुद्रण विवरणों onConsoleMessage(ConsoleMessage cm)को अपने लॉगकैट में प्राप्त करना चाहते हैं, तो आपको अपने WebChromeClient में विधि को लागू करना होगा । यह वेब कंसोल (इंस्पेक्ट एलिमेंट) जैसे पूर्ण स्टैक के निशान देता है। यहाँ विधि है।

public boolean onConsoleMessage(ConsoleMessage cm) 
    {
        Log.d("Message", cm.message() + " -- From line "
                             + cm.lineNumber() + " of "
                             + cm.sourceId() );
        return true;
    }

लागू करने के बाद आपको console.logअपने लॉग इन पर अपनी जावास्क्रिप्ट त्रुटियां और प्रिंट स्टेटमेंट मिलेंगे ।


2
मेरा मानना ​​है कि WebChromeClient पर है और WebViewClient नहीं है।
माइकल लेवी

हां आप सही हैं @MichaelLevy। मुझे उस गलती के लिए इशारा करने के लिए धन्यवाद। अब मैंने अपना उत्तर संपादित कर दिया है।
दिनेश

1
धन्यवाद, आपका जवाब सिर्फ वही था जो मुझे चाहिए था। मैं यह भी सुझाव दूंगा कि लोग WebChromeClient में onJsAlert () को ओवरराइड करें। जावास्क्रिप्ट में लॉग इन करते समय जावास्क्रिप्ट लॉगिंग और अलर्ट का संयोजन वास्तव में मददगार हो सकता है।
माइकल लेवी

13

@Ilya_Gazman उत्तर का संशोधन

    private void callJavaScript(WebView view, String methodName, Object...params){
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("javascript:try{");
        stringBuilder.append(methodName);
        stringBuilder.append("(");
        String separator = "";
        for (Object param : params) {               
            stringBuilder.append(separator);
            separator = ",";
            if(param instanceof String){
                stringBuilder.append("'");
            }
                stringBuilder.append(param.toString().replace("'", "\\'"));
            if(param instanceof String){
                stringBuilder.append("'");
            }

        }
        stringBuilder.append(")}catch(error){console.error(error.message);}");
        final String call = stringBuilder.toString();
        Log.i(TAG, "callJavaScript: call="+call);


        view.loadUrl(call);
    }

जेएस कॉल को सही तरीके से बनाएगा

callJavaScript(mBrowser, "alert", "abc", "def");
//javascript:try{alert('abc','def')}catch(error){console.error(error.message);}
callJavaScript(mBrowser, "alert", 1, true, "abc");
//javascript:try{alert(1,true,'abc')}catch(error){console.error(error.message);}

ध्यान दें कि वस्तुओं को सही ढंग से पारित नहीं किया जाएगा - लेकिन आप एक तर्क के रूप में पारित होने से पहले उन्हें क्रमबद्ध कर सकते हैं।

इसके अलावा, मैंने जहां त्रुटि की है, उसे बदल दिया है, मैंने इसे कंसोल लॉग में बदल दिया है जिसे निम्न द्वारा सुना जा सकता है:

    webView.setWebChromeClient(new CustomWebChromeClient());

और ग्राहक

class CustomWebChromeClient extends WebChromeClient {
    private static final String TAG = "CustomWebChromeClient";

    @Override
    public boolean onConsoleMessage(ConsoleMessage cm) {
        Log.d(TAG, String.format("%s @ %d: %s", cm.message(),
                cm.lineNumber(), cm.sourceId()));
        return true;
    }
}

धन्यवाद। क्या यह विधि किसी भी चर के अंदर 'वर्ण से बच जाएगी? दूसरे शब्दों में, क्या यह साथ काम करेगा callJavascript(mBrowser, "can't do it");:?
कोस्टानोस

1
बस उत्तर को संपादित किया और
कोस्टानोस

2

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>

MainActivity.java


import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.bluapp.androidview.R;

public class WebViewActivity3 extends AppCompatActivity {
    private WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_web_view3);
        webView = (WebView) findViewById(R.id.webView);
        webView.setWebViewClient(new WebViewClient());
        webView.getSettings().setJavaScriptEnabled(true);
        webView.loadUrl("file:///android_asset/webview1.html");


        webView.setWebViewClient(new WebViewClient(){
            public void onPageFinished(WebView view, String weburl){
                webView.loadUrl("javascript:testEcho('Javascript function in webview')");
            }
        });
    }
}

संपत्ति फ़ाइल

<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>WebView1</title>
<meta forua="true" http-equiv="Cache-Control" content="max-age=0"/>
</head>

<body style="background-color:#212121">
<script type="text/javascript">
function testEcho(p1){
document.write(p1);
}
</script>
</body>

</html>
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.