Многие приложения теперь имеют встроенные страницы HTML5, например те, которые часто меняются. Некоторым страницам требуется встроенная Java для взаимодействия с js в HTML5. Вот введение в использование HTML5 в Android:
1. О файлах cookie HTML5На веб-страницах могут использоваться многие параметры, такие как информация о пользователе. Вы можете заранее поместить эту информацию в файлы cookie. Вы можете использовать следующие методы:
public static void addCookies (контекст контекста, WebView webView, URL-адрес строки) { URL-адрес строки = https://www.xxxx.com/xx/xx/ Протокол строки = ; try { URL urlObj = новый URL (url) ; протокол = urlObj.getProtocol(); авторитет = urlObj.getAuthority() } catch (Исключение e) { e.printStackTrace(); String ua = webView.getSettings().getUserAgentString(); webView.getSettings().setUserAgentString(Constant.PROJECT_NAME + / + ParamHandler.getVersion(context) + ( + ua + ; HFWSH)); if (!TextUtils.isEmpty(url) && !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 data = new ArrayList(); this.clearExpired(); Значения коллекции = this.mCookies.values(); Iterator var3 =values.iterator(); () ) { SwiftCookie c = (SwiftCookie)var3.next(); data.add(c.toCookieString()); возвращаем данные; }Добавьте файл cookie перед mWebView.loadUrl(Url), и веб-страница сможет получить соответствующее значение параметра через файл cookie.
2. По поводу вопросов безопасности jsjs имел уязвимости до версии 4.2
С помощью JavaScript вы можете получить доступ ко всему, что находится на SD-карте текущего устройства, даже к контактной информации, текстовым сообщениям и т. д. Хорошо, давайте посмотрим, как произошла эта ошибка.
1. WebView добавляет объект JavaScript, и текущее приложение имеет разрешение на чтение и запись SDCard, то есть: android.permission.WRITE_EXTERNAL_STORAGE
2. В JS вы можете пройти по объекту окна, чтобы найти его с помощью метода getClass, затем получить объект среды выполнения с помощью механизма отражения, а затем вызвать статический метод для выполнения некоторых команд, например команд для доступа к файлам.
3. Затем получите строку из входного потока, возвращенную после выполнения команды, и вы сможете получить информацию об имени файла. Тогда ты можешь делать все, что хочешь, это так опасно. Основной код JS выглядит следующим образом:
function Execute(cmdArgs) { for (var obj in window) { if (getClass in window[obj]) { alert(obj); return window[obj].getClass().forName(java.lang.Runtime).getMethod( getRuntime, null).invoke(null,null).exec(cmdArgs) } } }; Решение: 1. Система Android 4,2 или вышеВ Android 4.2 и более поздних версиях Google внес исправление, объявив @JavascriptInterface в удаленном методе Java, как показано в следующем коде:
класс JsObject { @JavascriptInterface public String toString () { returnjectObject; } } webView.addJavascriptInterface(new JsObject(),jectObject); webView.loadData(, text/html, null); webView.loadUrl(javascript:alert(injectedObject. toString())); 2. Системы ниже Android 4.2.Эту проблему решить сложнее, но это не невозможно.
Прежде всего, мы определенно больше не можем вызывать метод addJavascriptInterface. Что касается этой проблемы, самое важное — знать действие события JS. Мы знаем, что существуют следующие типы взаимодействия между JS и Java, такие как приглашение, оповещение и т. д.
Такие действия будут соответствовать соответствующим методам в классе WebChromeClient. Для приглашения соответствующий метод — метод onJsPrompt. Объявление этого метода выглядит следующим образом:
общедоступное логическое значение onJsPrompt (представление WebView, строковый URL-адрес, строковое сообщение, строковое значение по умолчанию, результат 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)!='undefined') { console.log('window.jsInterface_js_interface_name существует!!');} else { window.jsInterface = { onButtonClick:function( arg0) {возврат Prompt('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onButtonClick',args:[arg0]}) }, onImageClick:function(arg0,arg1,arg2) { Prompt('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onImageClick',args:[arg0,arg1,arg2]}));проиллюстрировать:
1. jsInterface в приведенном выше коде — это имя регистрируемого объекта. Он регистрирует два метода: onButtonClick(arg0) и onImageClick(arg0, arg1, arg2). Если есть возвращаемое значение, добавьте return.
2. Приглашение — это согласованная нами строка, содержащая конкретный идентификатор MyApp:, за которым следует строка строк JSON, включающая имена методов, параметры, имена объектов и т. д.
3. Когда JS вызывает onButtonClick или onImageClick, он выполняет обратный вызов метода onJsPrompt на уровне Java. Затем мы анализируем имя метода, параметры, имя объекта, а затем рефлексивно вызываем метод.
4. window.jsInterface означает, что в окне объявлен объект Js. Форма объявленного метода: имя метода: функция (параметр 1, параметр 2).
3. Взаимодействие Java и JS в html51), Способ 1:
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 для вызова веб-просмотра на стороне Java
Имя метода 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 версия=1.0 кодировка=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 > <!-- кнопка демонстрирует веб-вызов Java --> <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. Java-код
//Загрузить веб-страницу сервера webView.loadUrl(https://www.baidu.com); //Должно иметь то же имя, что и функция js. webView.registerHandler(submitFromWeb, new BridgeHandler() { @Override public void handler(String data, CallBackFunction function) { String str =html данные возвращаются в java: + data; makeText(MainActivity.this, str, LENGTH_SHORT).show() ; Log.i(TAG, обработчик = submitFromWeb, данные из сети = + data.onCallBack(str +); , после обработки Java: + str.substring(,)); } }); // Имитируем пользователя для получения локального местоположения. User user = new User(); Location location = new Location.address = xxx; user.location = location; user.name = Брюс; webView.callHandler(functionInJs, new Gson().toJson(user), new CallBackFunction() { @Override public void onCallBack(String data) { makeText(MainActivity.this, веб-страница получает вашу информацию, LENGTH_SHORT).show() } }; webView.send(hello); webView.callHandler(functionInJs, data from Java, new CallBackFunction() { @Override public void onCallBack(String data) { // TODO Автоматически сгенерированная заглушка метода Log.i(TAG, данные ответа из js + data); } }) ;js-вызов
var str1 = document.getElementById(text1).value; var str2 = document.getElementById(text2).value; //вызов локального метода Java window.WebViewJavascriptBridge.callHandler('submitFromWeb', {'param': str}, function (ResponseData) { document.getElementById(show).innerHTML = отправить, получить данные ответа из Java, данные = + ответные данные } ); //Регистрируем прослушивание событий document.addEventListener( 'WebViewJavascriptBridgeReady', function() { callback(WebViewJavascriptBridge) }, false ); //Регистрируем функцию обратного вызова и вызываем функцию инициализации ConnectWebViewJavascriptBridge(function(bridge) { при подключении для первый раз Bridge.init(function(message, responseCallback) { console.log('JS получил сообщение', message); var data = { 'Javascript Отвечает': 'Wee!' }; console.log('JS отвечает', data responseCallback(data }); Bridge.registerHandler(functionInJs, function(data, responseCallback) { document.getElementById(show). InternalHTML = (данные из Java: = + data); var responseData = Javascript говорит: «Верно!»; responseCallback(responseData }); })4. Об оптимизации webView
1. Установите режим кэширования WebView.
Private void initWebView() { mWebView.getSettings().setJavaScriptEnabled(true); mWebView.getSettings().setRenderPriority(RenderPriority.HIGH); mWebView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT); //Установить режим кэширования// Включить API хранилища DOM Function mWebView.getSettings().setDomStorageEnabled(true); //Включаем функцию API хранилища базы данных mWebView.getSettings().setDatabaseEnabled(true); StringcacheDirPath = getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME; // StringcacheDirPath = 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 voidclearWebViewCache(){ //Очистить базу данных кеша Webview try { deleteDatabase(webview.db); deleteDatabase(webviewCache.db); catch (Exception e) { e.printStackTrace(); } //Файл кэша WebView File appCacheDir = new File(getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME); Log.e(TAG, путь appCacheDir=+appCacheDir.getAbsolutePath()); Файл webviewCacheDir = новый файл(getCacheDir().getAbsolutePath()+/webviewCache); Log.e(TAG, путь webviewCacheDir=+webviewCacheDir.getAbsolutePath()); ); //Удалить веб-просмотр Каталог кэша if(webviewCacheDir.exists()){ deleteFile(webviewCacheDir } //Удалить каталог кэша веб-просмотра if(appCacheDir.exists()){ deleteFile(appCacheDir } });3. При использовании WebView для загрузки веб-страниц некоторые фиксированные файлы ресурсов, такие как js/css/images и другие ресурсы, будут относительно большими. Если они загружаются непосредственно из сети, страница будет загружаться медленнее и потреблять больше трафика. Поэтому эти файлы следует поместить в ресурсы и упаковать вместе с приложением.
Чтобы решить эту проблему, используйте функцию mustInterceptRequest(представление WebView, 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, URL-адрес строки) {ответ WebResourceResponse = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {ответ = super.shouldInterceptRequest(view) ,url); если (url.contains(xxxxx.png)){попробуйте { response = new WebResourceResponse(image/png,UTF-8,getAssets().open(xxxxx.png) } catch (IOException e) { e.printStackTrace(); } } // return super.shouldInterceptRequest(view) , URL); вернуть ответ } @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public; WebResourceResponse mustInterceptRequest (представление WebView, запрос WebResourceRequest) {ответ WebResourceResponse = null; ответ = super.shouldInterceptRequest (представление, запрос); если (url.contains (xxxxx.png)) {попробуйте {ответ = новый WebResourceResponse (изображение/png, UTF). -,getAssets().open(xxxxx.png) } catch (IOException e) { e.printStackTrace() } } вернуть ответ;Выше приведено все содержание этой статьи. Я надеюсь, что она будет полезна для изучения всеми. Я также надеюсь, что все поддержат сеть VeVb Wulin.