تحتوي العديد من التطبيقات الآن على صفحات HTML5 مضمنة فيها، مثل تلك التي تتغير بشكل متكرر، وتتطلب بعض الصفحات لغة Java الأصلية للتفاعل مع js في HTML5:
1. حول ملفات تعريف الارتباط HTML5يمكن استخدام العديد من المعلمات مثل معلومات المستخدم في صفحات الويب، ويمكنك وضع هذه المعلومات في ملفات تعريف الارتباط مسبقًا، ويمكنك استخدام الطرق التالية:
public static void addCookies(Context context, WebView webView, String url) { String url=https://www.xxxx.com/xx/xx/ String Authority = ; حاول { URL urlObj = new URL(url) ;protocol = urlObj.getProtocol(); Authority = urlObj.getAuthority(); webView.getSettings().getUserAgentString(); webView.getSettings().setUserAgentString(Constant.PROJECT_NAME + / + ParamHandler.getVersion(context) + ( + ua + ; HFWSH)); !TextUtils.isEmpty(بروتوكول) && !TextUtils.isEmpty(authority)) { if (protocol.equals(https) && Authority.indexOf(liepin.com) > -1) { CookieSyncManager.createInstance(context); CookieManager cookieManager = CookieManager.getInstance(); (صحيح)؛ حاول { List<String> data = getCookiesString(); (!ListUtils.isEmpty(data)) { for (String value : data) { cookieManager.setCookie(url, value); } } cookieManager.setCookie(url,client_id= + Constant.CLIENT_ID + ;path=/;domain=. XXXX.com); cookieManager.setCookie(url, appVersion= + Constant .VERSION + ;path=/;domain=.XXXX.com); CookieSyncManager.getInstance().sync(); } Catch (Exception e) { LogUtils.e(Exception: + e.getMessage());
public List<String> getCookiesString() { بيانات ArrayList = new ArrayList(); قيم المجموعة = this.mCookies.values(); Iterator var3 =values.iterator(); () ) { SwiftCookie c = (SwiftCookie)var3.next(); data.add(c.toCookieString()) } return data; }
أضف ملف تعريف ارتباط قبل mWebView.loadUrl(Url)، ويمكن لصفحة الويب الحصول على قيمة المعلمة المقابلة من خلال ملف تعريف الارتباط.
2. فيما يتعلق بالقضايا الأمنية لـ jsكان لدى Node.js ثغرات أمنية قبل 4.2
من خلال JavaScript، يمكنك الوصول إلى أي شيء موجود على بطاقة SD الخاصة بالجهاز الحالي، حتى معلومات الاتصال والرسائل النصية وما إلى ذلك. حسنًا، دعونا نلقي نظرة على كيفية حدوث هذا الخطأ.
1. يضيف WebView كائن JavaScript، ويتمتع التطبيق الحالي بالإذن لقراءة وكتابة بطاقة SDCard، وهو: android.permission.WRITE_EXTERNAL_STORAGE
2. في JS، يمكنك اجتياز كائن النافذة للعثور على الكائن باستخدام طريقة getClass، ثم الحصول على كائن وقت التشغيل من خلال آلية الانعكاس، ثم استدعاء الطريقة الثابتة لتنفيذ بعض الأوامر، مثل أوامر الوصول إلى الملفات.
3. ثم احصل على السلسلة من دفق الإدخال الذي تم إرجاعه بعد تنفيذ الأمر، ويمكنك الحصول على معلومات اسم الملف. ثم يمكنك أن تفعل ما تريد، إنه أمر خطير للغاية. كود JS الأساسي هو كما يلي:
تنفيذ الوظيفة (cmdArgs) { for (var obj in window) { if (getClass in window[obj]) { تنبيه (obj)؛ return window[obj].getClass().forName(java.lang.Runtime) .getMethod( getRuntime,null).invoc(null,null).exec(cmdArgs);حل: 1. نظام أندرويد 4.2 أو أعلى
في Android 4.2 والإصدارات الأحدث، أجرت Google تصحيحًا من خلال الإعلان عن @JavascriptInterface على طريقة Java البعيدة، كما هو موضح في الكود التالي:
class JsObject { @JavascriptInterface public String toString() { return injectedObject } } webView.addJavascriptInterface(new JsObject(), injectedObject); toString()));2. أنظمة أقل من أندرويد 4.2
وهذه المشكلة أصعب في حلها، ولكنها ليست مستحيلة.
بادئ ذي بدء، لم يعد بإمكاننا بالتأكيد استدعاء طريقة addJavascriptInterface. فيما يتعلق بهذه المشكلة، فإن الشيء الأكثر أهمية هو معرفة إجراء حدث JS. نحن نعلم أن هناك أنواع التفاعل التالية بين JS وJava، مثل المطالبة والتنبيه وما إلى ذلك.
ستتوافق هذه الإجراءات مع الأساليب المقابلة في فئة WebChromeClient للمطالبة، والأسلوب المقابل لها هو أسلوب onJsPrompt.
منطقية عامة onJsPrompt (عرض WebView، عنوان URL لسلسلة، رسالة سلسلة، String defaultValue، نتيجة JsPromptResult)
من خلال هذه الطريقة، يمكن لـ JS تمرير المعلومات (النص) إلى Java، ويمكن لـ Java أيضًا تمرير المعلومات (النص) إلى JS. هل يمكننا إيجاد حل لهذه الفكرة؟
وبعد بعض التجارب والتحليل، وجدنا حلاً أكثر جدوى، يرجى الاطلاع على النقاط التالية:
[1] اسمح لـ JS باستدعاء طريقة Javascript. في هذه الطريقة، يتم استدعاء طريقة المطالبة، ويتم تمرير المعلومات الموجودة في JS من خلال المطالبة. يجب أن تكون هذه المعلومات نصًا ذا معنى نقوم بدمجه، والذي قد يتضمن: معرفات محددة، وأسماء الطرق ، المعلمات، الخ.
في طريقة onJsPrompt، نقوم بتحليل النص الذي تم تمريره للحصول على اسم الطريقة والمعلمات وما إلى ذلك، ثم نستدعي الطريقة المحددة من خلال آلية الانعكاس لاستدعاء طريقة كائن Java.
[2] فيما يتعلق بالقيمة المرجعة، يمكنك إرجاعها من خلال المطالبة، بحيث يمكن إرجاع نتائج معالجة الطريقة في Java إلى Js.
[3] نحتاج إلى إنشاء برنامج نصي JS ديناميكيًا يعلن عن طريقة Javascript، وتحميله من خلال LoadUrl، وتسجيله في صفحة html، والكود المحدد هو كما يلي:
javascript:(function JsAddJavascriptInterface_(){ if (typeof(window.jsInterface)!='undef') { console.log('window.jsInterface_js_interface_name موجود!!');} else { window.jsInterface = { onButtonClick:function( arg0) { عودة موجه('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onButtonClick',args:[arg0]}) }, onImageClick:function(arg0,arg1,arg2) { موجه('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onImageClick',args:[arg0,arg1,arg2]}));
يوضح:
1. jsInterface في الكود أعلاه هو اسم الكائن المراد تسجيله، وهو يسجل طريقتين، onButtonClick(arg0) وonImageClick(arg0, arg1, arg2).
2. الموجه هو السلسلة التي اتفقنا عليها، والتي تحتوي على المعرف المحدد MyApp:، متبوعًا بسلسلة من سلاسل JSON، والتي تتضمن أسماء الطرق والمعلمات وأسماء الكائنات وما إلى ذلك.
3. عندما يستدعي JS onButtonClick أو onImageClick، فإنه سيتصل مرة أخرى بطريقة onJsPrompt في طبقة Java، ثم نقوم بتحليل اسم الطريقة والمعلمات واسم الكائن، ثم نستدعي الطريقة بشكل عاكس.
4. window.jsInterface يعني أنه تم الإعلان عن كائن Js في النافذة، وشكل الطريقة المعلنة هو: اسم الطريقة: الوظيفة (المعلمة 1، المعلمة 2).
3. التفاعل بين Java وJS في html51)، الطريقة الأولى:
mWebView.getSettings().setJavaScriptEnabled(true);mWebView.addJavascriptInterface(this, xxx);
ثم قم بتنفيذ الطريقة التالية في الفصل الحالي:
@JavascriptInterface public void callbackFromH5(final String j) { // TODO }
يجب أن يكون اسم callbackFromH5 هو نفس اسم طريقة js في صفحة الويب
تستدعي Java طريقة js:
mWebView.loadUrl(String.format(javascript:java2js(0)));// هنا هو JS لاستدعاء عرض الويب على جانب جافا
يجب أن يكون اسم طريقة js متوافقًا مع صفحة الويب
2) الطريقة الثانية:
طريقة jsbridge (https://github.com/lzyzsd/JsBridge)
Android JsBridge هي أداة مساعدة تُستخدم لإنشاء جسر اتصال (اتصال) بين كود Java الأصلي ورمز JavaScript لتطبيق Android.
1 قم بتقديم jsBridge.jar في مشروعنا
أندرويد ستوديو:
المستودعات { // ... maven { url https://jitpack.io } } التبعيات { ترجمة 'com.github.lzyzsd:jsbridge:1.0.4' }
2. ملف التخطيط
<?xml version=1.0 encoding=utf-8?> <LinearLayout xmlns:android=http://schemas.android.com/apk/res/android android:layout_width=match_parent android:layout_height=match_parent android:orientation=vertical > <!-- زر يوضح اتصال جافا بالويب --> <Button android:id=@+id/button android:layout_width=match_parent android:text=@string/button_name android:layout_height=dp /> <!-- يعرض webview الاتصال عبر الويب Java --> <com.github.lzyzsd.jsbridge.BridgeWebView android:id=@+id/ webView android:layout_width=match_parent android:layout_height=match_parent> </com.github.lzyzsd.jsbridge.BridgeWebView> </LinearLayout>
3. كود جافا
// قم بتحميل صفحة ويب الخادم webView.loadUrl(https://www.baidu.com); // يجب أن يكون له نفس اسم وظيفة js. webView.registerHandler(submitFromWeb, new BridgeHandler() { @Override public void Handler(String data, CallBackFunction function) { String str =html data return to java: + data; makeText(MainActivity.this, str, LENGTH_SHORT).show() Log.i(TAG, Handler = SubmitFromWeb, data from web = + data); ، بعد معالجة Java: + str.substring(,)); // محاكاة المستخدم للحصول على الموقع المحلي User user = new User(); user.location = location; user.name = Bruce; webView.callHandler(functionInJs, new Gson().toJson(user), new CallBackFunction() { @Override public void onCallBack(String data) { makeText(MainActivity.this، صفحة الويب تحصل على معلوماتك، LENGTH_SHORT).show() } });
webView.callHandler(functionInJs, data from Java, new CallBackFunction() { @Override public void onCallBack(String data) { // TODO Auto-generated way stub Log.i(TAG, بيانات الاستجابة من js + data); } }) ;
مكالمة شبيبة
var str1 = document.getElementById(text1).value; var str2 = document.getElementById(text2).value; // استدعاء نافذة طريقة جافا المحلية.WebViewJavascriptBridge.callHandler( 'submitFromWeb' , {'param': str} , function (استجابة البيانات) { document.getElementById(show).innerHTML = إرسال الحصول على بيانات الاستجابة من جافا، البيانات = + بيانات الاستجابة } ); // تسجيل الاستماع للحدث document.addEventListener( 'WebViewJavascriptBridgeReady' , function() { callback(WebViewJavascriptBridge) }, false ); المرة الأولى Bridge.init(function(message, ResponseCallback) { console.log('JS حصلت على رسالة', message); var data = { 'Javascript Responds': 'Wee!' }; console.log('JS يستجيب بـ', data);responsCallback(data }); الداخليHTML = (بيانات من Java: = + data var ResponseData = Javascript Says Right back aka!; })
4. حول تحسين عرض الويب
1. قم بتعيين وضع ذاكرة التخزين المؤقت لـ WebView
Private void initWebView() { mWebView.getSettings().setJavaScriptEnabled(true); mWebView.getSettings().setRenderPriority(RenderPriority.HIGH); تمكين واجهة برمجة تطبيقات تخزين DOM الوظيفة mWebView.getSettings().setDomStorageEnabled(true); // تمكين وظيفة واجهة برمجة التطبيقات لتخزين قاعدة البيانات mWebView.getSettings().setDatabaseEnabled(true); StringacheDirPath = getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME; getCacheDir().getAbsolutePath()+Constant.APP_DB_DIRNAME; Log.i(TAG, CacheDirPath=+cacheDirPath); // تعيين مسار ذاكرة التخزين المؤقت لقاعدة البيانات mWebView.getSettings().setDatabasePath(cacheDirPath); mWebView.getSettings().setAppCachePath(cacheDirPath); // تمكين وظيفة ذاكرة التخزين المؤقت للتطبيق mWebView.getSettings().setAppCacheEnabled(true);
2. مسح ذاكرة التخزين المؤقت
/** * مسح ذاكرة التخزين المؤقت لـ WebView*/ public void ClearWebViewCache(){ // مسح قاعدة بيانات ذاكرة التخزين المؤقت لـ Webview حاول {deleteDatabase(webview.db); } // ملف ذاكرة التخزين المؤقت WebView File appCacheDir = new File(getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME); Log.e(TAG, appCacheDir path=+appCacheDir.getAbsolutePath()); ملف webviewCacheDir = new File(getCacheDir().getAbsolutePath()+/webviewCache()); ); //حذف عرض الويب دليل ذاكرة التخزين المؤقت if(webviewCacheDir.exists()){deleteFile(webviewCacheDir); } // حذف دليل ذاكرة التخزين المؤقت لعرض الويب if(appCacheDir.exists()){deleteFile(appCacheDir);
3. عند استخدام WebView لتحميل صفحات الويب، ستكون بعض ملفات الموارد الثابتة مثل js/css/images والموارد الأخرى كبيرة نسبيًا، وإذا تم تحميلها مباشرة من الشبكة، فسيتم تحميل الصفحة بشكل أبطأ وتستهلك المزيد من حركة المرور. لذلك يجب وضع هذه الملفات في الأصول وتعبئتها مع التطبيق.
لحل هذه المشكلة، استخدم وظيفة mustInterceptRequest(WebView view, String url) التي توفرها API 11 (HONEYCOMB) لتحميل الموارد المحلية.
أوقفت واجهة برمجة التطبيقات (API 21) هذه الطريقة مرة أخرى وأضفت تحميلًا زائدًا على mustInterceptRequest الجديد، واستبدلت المعلمات المطلوبة عنوان url بالطلب.
على سبيل المثال، هناك صورة xxxxx.png. تم وضع هذه الصورة في الأصول. الآن بعد أن تم تحميل HTML خارجي، يجب إخراج الصورة الموجودة في الأصول مباشرة وتحميلها دون إعادة الحصول عليها من الشبكة. بالطبع، يمكنك تغيير رابط الصورة في HTML إلى file:///android_asset/xxxxx.png،
ولكن لا يمكن مشاركة HTML هذا في Android وiOS وWAP.
webView.setWebViewClient(new WebViewClient() { @Override public WebResourceResponse mustInterceptRequest(WebView view, String url) { WebResourceResponse Response = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){ Response = super.shouldInterceptRequest(view ,url); if (url.contains(xxxxx.png)){ حاول { Response = new WebResourceResponse(image/png,UTF-8,getAssets().open(xxxxxx.png)); } Catch (IOException e) { e.printStackTrace(); } } } // return super.shouldInterceptRequest(view , url); إرجاع الاستجابة } @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public WebResourceResponse mustInterceptRequest(WebView view, WebResourceRequest request) { استجابة WebResourceResponse = null; Response = super.shouldInterceptRequest(view, request); -,getAssets().open(xxxxx.png)); Catch (IOException e) { e.printStackTrace(); } } إرجاع الاستجابة;
ما ورد أعلاه هو المحتوى الكامل لهذه المقالة وآمل أن يكون مفيدًا لدراسة الجميع وآمل أيضًا أن يدعم الجميع شبكة VeVb Wulin.