Qt5.6 安卓下的WebView如何實現(xiàn)JavaScript通信?
Qt官方的Webview僅僅在Qtquick中支持安卓和ios,安卓的官方實現(xiàn)是調(diào)用安卓系統(tǒng)自帶的瀏覽器API,但是Qt官方?jīng)]有寫js交互,于是研究了一通宵得出幾個解決方案:
1.使用Qt官方的QML webview和HTML5的Websockt,在js中使用websockt,在qt qucik中使用websocket服務器,結果可行,可惜安卓很多版本不支持Websockt,于是乎3個小時過去了。
2.既然websockt行不通,就想了下socket.io庫,能運行~可惜qt quick的Websockt服務器不支持socket.io的協(xié)議,于是乎 3小時又浪費了
3.使用HTML sockt或post,post要執(zhí)行的函數(shù),用QML的eval函數(shù)來執(zhí)行字符串代碼,于是乎用xhl來發(fā)送post數(shù)據(jù),然后用C++建立TcpSocket來接收,但是我放棄了,解析HTML封包不劃算,為了發(fā)送4個字符他會發(fā)一大堆HTML協(xié)議字符串…因為 socket由C++接收.websockt在 qt quick中,js post->sockt->qt quick 要跨3層交互才收的到數(shù)據(jù),實在蛋疼…更重要的是還要避免意外情況,于是乎2小時又浪費了
4.最后花了5個小時,在國外看到一些開源代碼,經(jīng)過修改 實現(xiàn)了原生交互,依然是調(diào)用安卓的webview,內(nèi)嵌到qt中
具體實現(xiàn):c++ –> java ?–> js
因為安卓的瀏覽器和java的交互是最穩(wěn)定的
先生成Qt 安卓項目,先編譯一次,在目錄下新建android文件夾(QT中可以創(chuàng)建) 和 assets文件夾
把androud-build中的src目錄下全部文件復制到android目錄,打開eclipse,在QtActivity包下添加一個類:
下面代碼是參考過來的:
package?org.qtproject.qt5.android.bindings; public?interface?NativeCalls?{ ????public?void?createNewWebView(int?tag); ????public?void?removeWebView(int?tag); ????public?void?moveWebView(int?tag,?int?x,?int?y); ????public?void?resizeWebView(int?tag,?int?w,?int?h); ????public?void?attachWebViewToMainLayout(int?tag); ????public?void?loadUrlAtWebView(int?tag,?String?url); ????public?void?loadHtmlAtWebView(int?tag,?String?html);? }
然后再添加一個類,用來繼承webview,定制一些功能,比如開啟js和彈窗等,并且添加JavaScript交互接口,接口函數(shù)在C++中定義,在JAVA中聲明、
package?org.qtproject.qt5.android.bindings; import?android.webkit.WebView; import?android.webkit.WebViewClient; import?android.widget.FrameLayout; import?android.webkit.*; import?android.content.Context; import?android.util.Log; public?class?Cjavascript??{ ????public?Cjavascript??(?)?{ ????} ????public??native?int??testcall2(); ????public??native?void??testcall3(); ????public??native?void??testcall4(); ????public??void?testcall() ????{ ????????Log.i("testcalltestcalltestcalltestcall",?"call:"); ????} }
package?org.qtproject.qt5.android.bindings; import?android.annotation.SuppressLint; import?android.content.Context; import?android.graphics.Color; import?android.webkit.JsResult; import?android.webkit.WebChromeClient; import?android.webkit.WebView; import?android.webkit.WebViewClient; public?class?MyWebView?extends?WebView?{ ????public?MyWebView(Context?context)?{ ????????super(context);? ????????init(); ????????//?TODO?自動生成的構造函數(shù)存根 ????} ????@SuppressLint("SetJavaScriptEnabled") ????public?void??init()?{ ????????this.getSettings().setJavaScriptEnabled(true); ????????this.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); ????????????//否則不會執(zhí)行js的Alert ????????this.setWebChromeClient(new?WebChromeClient() ????????????{???public?boolean?onJsAlert(WebView?view,?String?url,?String?message, ????????????????????????JsResult?result) ????????????????{ ????????????????????//Auto-generated?method?stub ????????????????????return?super.onJsAlert(view,?url,?message,?result); ????????????????} ????????????}); ????????this.setWebViewClient(new?WebViewClient()); ????????this.setBackgroundColor(Color.BLACK);? ????????this.addJavascriptInterface(new?Cjavascript(),?"obj"); ????} }
最后就是修改Qt自己生成的QtActivity類,在作用域中添加以下代碼即可:
下面的代碼大部分參考別人的,少量修改。官方源碼中都是使用RunOnUiThread,下面的是用handle進行多線程界面操作。
?//-------------WEBVIEW---------------- ????protected?ArrayListwebViewsList?=?new?ArrayList(); ????//----------------------------------------------------------------------------- ????protected?MyWebView?findWebViewByTag(int?tag)?{ ????????MyWebView?webViewRes?=?null; ????????for?(int?i?=?0;?i?<?webViewsList.size();?i++)?{ ????????????MyWebView?wv?=?(MyWebView)?webViewsList.get(i); ????????????if?(((Integer)wv.getTag()).intValue()?==?tag)?{ ????????????????webViewRes?=?wv; ????????????????break; ????????????} ????????} ????????return?webViewRes; ????} ????//----------------------------------------------------------------------------- ????@Override ????public?void?createNewWebView(int?tag)?{ ????????Message?msg?=?new?Message(); ????????msg.what?=?tag; ????????createNewWebViewHandler.sendMessage(msg); ????} ????protected?Handler?createNewWebViewHandler?=?new?Handler()?{ ????????@SuppressLint("SetJavaScriptEnabled") ????????@Override ????????public?void?handleMessage(Message?msg)?{ ????????????MyWebView?webView?=?new?MyWebView(QtActivity.this); ????????????webView.setTag(msg.what); //??????????????webView.getSettings().setJavaScriptEnabled(true); //??????????????webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); //??????????????//否則不會執(zhí)行js的Alert //??????????????webView.setWebChromeClient(new?WebChromeClient() //??????????????{???public?boolean?onJsAlert(WebView?view,?String?url,?String?message, //??????????????????????????JsResult?result) //??????????????????{ //??????????????????????//Auto-generated?method?stub //??????????????????????return?super.onJsAlert(view,?url,?message,?result); //??????????????????} // //??????????????}); //??????????????webView.setWebViewClient(new?WebViewClient()); //??????????????webView.setBackgroundColor(Color.BLACK);? ????????????webViewsList.add(webView);? ????????} ????}; ????//----------------------------------------------------------------------------- ????@Override ????public?void?removeWebView(int?tag)?{ ????????Message?msg?=?new?Message(); ????????msg.what?=?tag; ????????removeWebViewHandler.sendMessage(msg); ????} ????protected?Handler?removeWebViewHandler?=?new?Handler()?{ ????????@Override ????????public?void?handleMessage(Message?msg)?{ ????????????MyWebView?webView?=?findWebViewByTag(msg.what); ????????????if?(webView?!=?null)?{ ????????????????webViewsList.remove(webView); ????????????????FrameLayout?mainLayout?=?(FrameLayout)?findViewById(R.id.content); ????????????????mainLayout.removeView(webView); ????????????} ????????} ????}; ????//----------------------------------------------------------------------------- ????@Override ????public?void?moveWebView(int?tag,?int?x,?int?y)?{ ????????Message?msg?=?new?Message(); ????????msg.what?=?tag; ????????msg.arg1?=?x; ????????msg.arg2?=?y; ????????moveWebViewHandler.sendMessage(msg); ????} ????protected?Handler?moveWebViewHandler?=?new?Handler()?{ ????????@Override ????????public?void?handleMessage(Message?msg)?{ ????????????View?viewToMove?=?null; ????????????viewToMove?=?findWebViewByTag(msg.what); ????????????if?(viewToMove?!=?null)?{ ????????????????FrameLayout.LayoutParams?params?=?(android.widget.FrameLayout.LayoutParams)?viewToMove ????????????????????????.getLayoutParams(); ????????????????params.leftMargin?=?msg.arg1; ????????????????params.topMargin?=?msg.arg2; ????????????????viewToMove.setLayoutParams(params); ????????????} ????????} ????}; ????//----------------------------------------------------------------------------- ????@Override ????public?void?resizeWebView(int?tag,?int?w,?int?h)?{ ????????Message?msg?=?new?Message(); ????????msg.what?=?tag; ????????msg.arg1?=?w; ????????msg.arg2?=?h; ????????resizeWebViewHandler.sendMessage(msg); ????} ????protected?Handler?resizeWebViewHandler?=?new?Handler()?{ ????????@Override ????????public?void?handleMessage(Message?msg)?{ ????????????View?viewToResize?=?null; ????????????viewToResize?=?findWebViewByTag(msg.what); ????????????if?(viewToResize?!=?null)?{ ????????????????FrameLayout.LayoutParams?params?=?(android.widget.FrameLayout.LayoutParams)?viewToResize ????????????????????????.getLayoutParams(); ????????????????params.width?=?msg.arg1; ????????????????params.height?=?msg.arg2; ????????????????viewToResize.setLayoutParams(params); ????????????} ????????} ????}; ????//----------------------------------------------------------------------------- ????@Override ????public?void?attachWebViewToMainLayout(int?tag)?{ ????????Message?msg?=?new?Message(); ????????msg.what?=?tag; ????????attachWebViewToMainLayoutHandler.sendMessage(msg); ????} ????protected?Handler?attachWebViewToMainLayoutHandler?=?new?Handler()?{ ????????@Override ????????public?void?handleMessage(Message?msg)?{ ????????????View?viewToAttach?=?null; ????????????viewToAttach?=?findWebViewByTag(msg.what); ????????????if?(viewToAttach?!=?null)?{ ????????????????FrameLayout?mainLayout?=?(FrameLayout)?findViewById(R.id.content); ????????????????FrameLayout.LayoutParams?params?=?new?FrameLayout.LayoutParams(100,?100); ????????????????params.leftMargin?=?0; ????????????????params.topMargin?=?0; ????????????????mainLayout.addView(viewToAttach,?params); ????????????} ????????} ????}; ????//----------------------------------------------------------------------------- ????@Override ????public?void?loadUrlAtWebView(int?tag,?String?url)?{ ????????Log.i("url",?"curid:"+Thread.currentThread().getId()); ????????Message?msg?=?new?Message(); ????????msg.what?=?tag; ????????msg.obj?=?url; ?????????loadUrlAtWebViewHandler.sendMessage(msg); ????} ????protected?Handler?loadUrlAtWebViewHandler?=?new?Handler()?{ ????????@Override ????????public?void?handleMessage(Message?msg)?{ ????????????Log.i("url",?"mainid:"+Thread.currentThread().getId()); ????????????MyWebView?webView?=?findWebViewByTag(msg.what); ????????????if?(webView?!=?null)?{ ????????????????webView.loadUrl(msg.obj.toString()); ????????????????Log.i("url",?msg.obj.toString()); ????????????} ????????????//Log.i("TestNative*********",?"call:"); ????????????//TestNative??testNative??=?new?TestNative(); ????????????//testNative.Test(); ????????} ????}; ????//----------------------------------------------------------------------------- ????@Override ????public?void?loadHtmlAtWebView(int?tag,?String?html)?{ ????????Message?msg?=?new?Message(); ????????msg.what?=?tag; ????????msg.obj?=?html; ????????loadHtmlAtWebViewHandler.sendMessage(msg); ????} ????protected?Handler?loadHtmlAtWebViewHandler?=?new?Handler()?{ ????????@Override ????????public?void?handleMessage(Message?msg)?{ ????????????MyWebView?webView?=?findWebViewByTag(msg.what); ????????????if?(webView?!=?null)?{ ????????????????webView.loadData(msg.obj.toString(),?"text/html;?charset=UTF-8",?"UTF-8"); ????????????} ????????} ????};
C++層,注冊JavaScript函數(shù):
#ifndef?JAVA_JAVASCTRIPTFUNC_H #define?JAVA_JAVASCTRIPTFUNC_H #include#include#includeclass?JAVA_javasctriptFunc { public: ????JAVA_javasctriptFunc(); ????bool?regfuc(); }; #endif?//?JAVA_JAVASCTRIPTFUNC_H #include?"java_javasctriptfunc.h" int?cout=0; static?jint?testcall2(JNIEnv?*env,?jobject?thiz) { ????cout++; ???qInfo()?<<?"MY?C+++:?testcall2"<<QThread::currentThreadId()?; ???return?cout; ???????//?QMessageBox::information(NULL,"HEHE","33"); } static?void?testcall3(JNIEnv?*env,?jobject?thiz) { ???qInfo()?<<?"MY?C+++:?testcall3"<<QThread::currentThreadId()??; ???????//?QMessageBox::information(NULL,"HEHE","33"); } static?void?testcall4(JNIEnv?*env,?jobject?thiz) { ???qInfo()?<<?"MY?C+++:?testcall4"<GetObjectClass(javaClass.object()); ?????qDebug()?<<?"find?ExtendsQtNative?-?"?<<?clazz; ?????bool?result?=?false; ?????if(clazz) ?????{ ?????????jint?ret?=?env->RegisterNatives(clazz, ?????????????????????????????????????????methods, ?????????????????????????????????????????sizeof(methods)?/?sizeof(methods[0])); ?????????env->DeleteLocalRef(clazz); ?????????qDebug()?<<?"RegisterNatives?return?-?"?<<?ret; ?????????result?=?ret?>=?0; ?????} ?????if(env->ExceptionCheck())?env->ExceptionClear(); ?????return?result; ?}
WEBVIEW的C++層實現(xiàn):
#pragma?once #include#include#includeclass?CAndroidNativeCallsSender { public: ????CAndroidNativeCallsSender(); ????~CAndroidNativeCallsSender(); ????void?createNewWebView(?int?id?)?const; ????void?removeWebView(?int?id?)?const; ????void?attachWebViewToMainLayout(?int?id?)?const; ????void?moveWebView(?int?id,?int?x,?int?y?)?const; ????void?resizeWebView(?int?id,?int?w,?int?h?)?const; ????void?loadUrlAtWebView(?int?id,?QString?const&?url?)?const; ????void?loadHtmlAtWebView(?int?id,?QString?const&?html?)?const; protected: ????jmethodID?m_createNewWebViewMID; ????jmethodID?m_removeWebViewMID; ????jmethodID?m_attachWebViewToMainLayoutMID; ????jmethodID?m_moveWebViewMID; ????jmethodID?m_resizeWebViewMID; ????jmethodID?m_loadUrlAtWebViewMID; ????jmethodID?m_loadHtmlAtWebViewMID; ????jobject?m_objectRef; };
#include?"AndroidNativeCallsSender.h" #include//----------------------------------------------------------------------------- CAndroidNativeCallsSender::CAndroidNativeCallsSender() { ????QAndroidJniEnvironment?jniEnv; ????QAndroidJniObject?qObjAct?=?QAndroidJniObject::callStaticObjectMethod(?"org/qtproject/qt5/android/QtNative", ???????????????????????????????????????????????????????????????????????????"activity", ???????????????????????????????????????????????????????????????????????????"()Landroid/app/Activity;"?); ????jobject?objAct?=?qObjAct.object(); ????m_objectRef?=?jniEnv->NewGlobalRef(?objAct?); ????jclass?cls?=?jniEnv->GetObjectClass(?objAct?); ????if(?cls?) ????{ ????????m_createNewWebViewMID?=?jniEnv->GetMethodID(?cls,?"createNewWebView",?"(I)V"?); ????????m_removeWebViewMID?=?jniEnv->GetMethodID(?cls,?"removeWebView",?"(I)V"?); ????????m_attachWebViewToMainLayoutMID?=?jniEnv->GetMethodID(?cls,?"attachWebViewToMainLayout",?"(I)V"?); ????????m_moveWebViewMID?=?jniEnv->GetMethodID(?cls,?"moveWebView",?"(III)V"?); ????????m_resizeWebViewMID?=?jniEnv->GetMethodID(?cls,?"resizeWebView",?"(III)V"?); ????????m_loadUrlAtWebViewMID?=?jniEnv->GetMethodID(?cls,?"loadUrlAtWebView",?"(ILjava/lang/String;)V"?); ????????m_loadHtmlAtWebViewMID?=?jniEnv->GetMethodID(?cls,?"loadHtmlAtWebView",?"(ILjava/lang/String;)V"?); ????} } //----------------------------------------------------------------------------- CAndroidNativeCallsSender::~CAndroidNativeCallsSender() { ????if(?m_objectRef?!=?NULL?) ????{ ????????QAndroidJniEnvironment?jniEnv; ????????jniEnv->DeleteGlobalRef(?m_objectRef?); ????} } //----------------------------------------------------------------------------- void?CAndroidNativeCallsSender::createNewWebView(?int?id?)?const { ????if(?m_createNewWebViewMID?) ????{ ????????QAndroidJniEnvironment?jniEnv; ????????jniEnv->CallVoidMethod(?m_objectRef,?m_createNewWebViewMID,?id?); ????} } //----------------------------------------------------------------------------- void?CAndroidNativeCallsSender::removeWebView(?int?id?)?const { ????if(?m_removeWebViewMID?) ????{ ????????QAndroidJniEnvironment?jniEnv; ????????jniEnv->CallVoidMethod(?m_objectRef,?m_removeWebViewMID,?id?); ????} } //----------------------------------------------------------------------------- void?CAndroidNativeCallsSender::attachWebViewToMainLayout(?int?id?)?const { ????if(?m_attachWebViewToMainLayoutMID?) ????{ ????????QAndroidJniEnvironment?jniEnv; ????????jniEnv->CallVoidMethod(?m_objectRef,?m_attachWebViewToMainLayoutMID,?id?); ????} } //----------------------------------------------------------------------------- void?CAndroidNativeCallsSender::moveWebView(?int?id,?int?x,?int?y?)?const { ????if(?m_moveWebViewMID?) ????{ ????????QAndroidJniEnvironment?jniEnv; ????????jniEnv->CallVoidMethod(?m_objectRef,?m_moveWebViewMID,?id,?x,?y?); ????} } //----------------------------------------------------------------------------- void?CAndroidNativeCallsSender::resizeWebView(?int?id,?int?w,?int?h?)?const { ????if(?m_resizeWebViewMID?) ????{ ????????QAndroidJniEnvironment?jniEnv; ????????jniEnv->CallVoidMethod(?m_objectRef,?m_resizeWebViewMID,?id,?w,?h?); ????} } //----------------------------------------------------------------------------- void?CAndroidNativeCallsSender::loadUrlAtWebView(?int?id,?QString?const&?url?)?const { ????if(?m_loadUrlAtWebViewMID?) ????{ ????????QAndroidJniEnvironment?jniEnv; ????????jstring?jurl?=?jniEnv->NewStringUTF(?url.toUtf8().constData()?); ????????jniEnv->CallVoidMethod(?m_objectRef, ????????????????????????????????m_loadUrlAtWebViewMID, ????????????????????????????????id, ????????????????????????????????jurl?); ????????jniEnv->DeleteLocalRef(?jurl?); ????} } //----------------------------------------------------------------------------- void?CAndroidNativeCallsSender::loadHtmlAtWebView(?int?id,?QString?const&?html?)?const { ????if(?m_loadUrlAtWebViewMID?) ????{ ????????QAndroidJniEnvironment?jniEnv; ????????jstring?jhtml?=?jniEnv->NewStringUTF(?html.toUtf8().constData()?); ????????jniEnv->CallVoidMethod(?m_objectRef, ????????????????????????????????m_loadHtmlAtWebViewMID, ????????????????????????????????id, ????????????????????????????????jhtml?); ????????jniEnv->DeleteLocalRef(?jhtml?); ????} }
#pragma?once #include#include#include?"AndroidNativeCallsSender.h" class?QtCustomAndroidWebView?:?public?QWidget { ????Q_OBJECT public: ????explicit?QtCustomAndroidWebView(?QWidget?*parent?=?0?); ????~QtCustomAndroidWebView(); ????void?loadURL(?QString?const&?url?)?const; ????void?loadHtmlData(?QString?const&?data?)?const; ????void?move(?int?x,?int?y?); ????void?move(?QPoint?const&?p?); ????void?resize(?int?w,?int?h?); ????int?androidID()?const?{?return?m_androidID;?} protected: ????static?int?sm_tag; ????int?m_androidID; ????CAndroidNativeCallsSender?m_nativeSender; ????int?generateNewTag(); signals: public?slots: };
#include?"QtCustomAndroidWebView.h" //#include//----------------------------------------------------------------------------- int?QtCustomAndroidWebView::sm_tag?=?0; //----------------------------------------------------------------------------- QtCustomAndroidWebView::QtCustomAndroidWebView(?QWidget?*parent?) ????:?QWidget(?parent?) ????,?m_androidID(?generateNewTag()?) { //????if(?parent?&&?parent->layout()?) //????????parent->layout()->addWidget(?this?); ????m_nativeSender.createNewWebView(?androidID()?); ????m_nativeSender.attachWebViewToMainLayout(?androidID()?); } //----------------------------------------------------------------------------- QtCustomAndroidWebView::~QtCustomAndroidWebView() { ????m_nativeSender.removeWebView(?androidID()?); } //----------------------------------------------------------------------------- void?QtCustomAndroidWebView::loadURL(?QString?const&?url?)?const { ????m_nativeSender.loadUrlAtWebView(?androidID(),?url?); } //----------------------------------------------------------------------------- void?QtCustomAndroidWebView::loadHtmlData(?QString?const&?data?)?const { ????m_nativeSender.loadHtmlAtWebView(?androidID(),?data?); } //----------------------------------------------------------------------------- void?QtCustomAndroidWebView::move(?int?x,?int?y?) { ????QWidget::move(?x,?y?); ????m_nativeSender.moveWebView(?androidID(),?x,?y?); } //----------------------------------------------------------------------------- void?QtCustomAndroidWebView::move(?QPoint?const&?p?) { ????QtCustomAndroidWebView::move(?p.x(),?p.y()?); } //----------------------------------------------------------------------------- void?QtCustomAndroidWebView::resize(?int?w,?int?h?) { ????QWidget::resize(?w,?h?); ????m_nativeSender.resizeWebView(?androidID(),?w,?h?); } //----------------------------------------------------------------------------- int?QtCustomAndroidWebView::generateNewTag() { ????sm_tag++; ????return?sm_tag; }
測試代碼
#include?"mytest.h" #include?"QtCustomAndroidWebView.h" #include#include#include#includeMyTest::MyTest(QWidget?*parent)?:?QWidget(parent) { ????vbox?=?new?QVBoxLayout(this); ????btn?=?new?QPushButton("call"); ????btn->setText("CALL"); ????edit?=?new?QTextEdit(); ??????vbox->addWidget(btn); ??????vbox->addWidget(edit); //????webview?=?new?QtCustomAndroidWebView(); //????webview->resize(this->width(),this->height()); //???webview->move(0,0); //???webview->loadURL("http://www.baidu.com"); //???vbox->addWidget(webview); ?QScreen?*screen?=?QApplication::primaryScreen(); ???webview?=?new?QtCustomAndroidWebView(?); ?????webview->resize(this->width(),?200); ?????webview->loadURL("file:///android_asset/index.html"); ????//注冊js函數(shù) ?????javajavasctriptFunc?=?new?JAVA_javasctriptFunc(); ?????if(javajavasctriptFunc->regfuc()==false) ?????{ ????????????????qDebug()<addWidget(webview); ??????connect(btn,SIGNAL(clicked(bool)),this,SLOT(onclick())); } ?void??MyTest::onclick() ?{ ?????int?cout=0; ?????while?(1)?{ ?????????QThread::msleep(200); ?????????QString?s; ?????????s.sprintf("javascript:test2(%d)",cout); ?????????cout++; ?????????webview->loadURL(s); //??????執(zhí)行js腳本?返回值可參考Qt?android?src中WebView的實現(xiàn)?????webview->loadURL("javascript:test()"); ?????} ?}
$(function(){ ????$("button").click(function(){ ????var??x=obj.testcall2(); ?????????$("#list1").append("Inbox"+x+""); ????????$('#list1').listview("refresh"); ??}); });
如何調(diào)用JavaScript能獲取返回值,可參考Qt的源碼,其實沒啥必要,只需要注冊一個函數(shù)給js調(diào)用,讓他把返回值弄進來就是
?m_webSettingsSetDisplayZoomControls?=?webSettings.getClass().getMethod("setDisplayZoomControls",?boolean.class); ????????????????????????if?(Build.VERSION.SDK_INT?>?18)?{ ????????????????????????????m_webViewEvaluateJavascript?=?m_webView.getClass().getMethod("evaluateJavascript", ?????????????????????????????????????????????????????????????????????????????????????????String.class, ?????????????????????????????????????????????????????????????????????????????????????????ValueCallback.class); ????????????????????????}
????public?void?runJavaScript(final?String?script,?final?long?callbackId) ????{ ????????if?(script?==?null) ????????????return; ????????if?(Build.VERSION.SDK_INT?<?19?||?m_webViewEvaluateJavascript?==?null) ????????????return; ????????m_activity.runOnUiThread(new?Runnable()?{ ????????????@Override ????????????public?void?run()?{ ????????????????try?{ ????????????????????m_webViewEvaluateJavascript.invoke(m_webView,?script,?callbackId?==?-1???null?: ????????????????????????new?ValueCallback()?{ ????????????????????????????@Override ????????????????????????????public?void?onReceiveValue(String?result)?{ ????????????????????????????????c_onRunJavaScriptResult(m_id,?callbackId,?result); ????????????????????????????} ????????????????????????}); ????????????????}?catch?(Exception?e)?{ ????????????????????e.printStackTrace(); ????????????????} ????????????} ????????}); ????}