Muchas aplicaciones ahora tienen páginas HTML5 integradas, como las que cambian con frecuencia. Algunas páginas requieren Java nativo para interactuar con js en HTML5. Aquí hay una introducción al uso de HTML5 en Android.
1. Acerca de las cookies HTML5Se pueden utilizar muchos parámetros, como la información del usuario, en las páginas web. Puede colocar esta información en cookies con antelación. Puede utilizar los siguientes métodos:
addCookies vacías estáticas públicas (contexto de contexto, WebView webView, URL de cadena) { URL de cadena = https://www.xxxx.com/xx/xx/ Protocolo de cadena = autoridad de cadena = intentar { URL urlObj = nueva URL (url) ; protocolo = urlObj.getProtocol(); autoridad = urlObj.getAuthority(); captura (Excepción e) { e.printStackTrace(); webView.getSettings().getUserAgentString(); webView.getSettings().setUserAgentString(Constant.PROJECT_NAME + / + ParamHandler.getVersion(context) + ( + ua + ; HFWSH)); !TextUtils.isEmpty(protocolo) && !TextUtils.isEmpty(autoridad)) { if (protocol.equals(https) && autoridad.indexOf(liepin.com) > -1) { CookieSyncManager.createInstance(context); CookieManager cookieManager = CookieManager.getInstance(); (verdadero); intente { Lista<Cadena> datos = getCookiesString(); (!ListUtils.isEmpty(data)) { for (Valor de cadena: datos) { cookieManager.setCookie(url, valor } } cookieManager.setCookie(url, client_id= + Constant.CLIENT_ID + ;path=/;domain=. XXXX.com); cookieManager.setCookie(url, appVersion= + Constante .VERSION + ;ruta=/;dominio=.XXXX.com); CookieSyncManager.getInstance().sync(); } catch (Excepción e) { LogUtils.e(Excepción: + e.getMessage()); Lista pública<String> getCookiesString() { ArrayList datos = new ArrayList(); this.clearExpired(); Valores de colección = this.mCookies.values(); () ) { SwiftCookie c = (SwiftCookie)var3.next(); data.add(c.toCookieString() } devuelve datos; }Agregue una cookie antes de mWebView.loadUrl (Url) y la página web podrá obtener el valor del parámetro correspondiente a través de la cookie.
2. Respecto a los problemas de seguridad de js.js tenía vulnerabilidades antes de 4.2
A través de JavaScript, puede acceder a cualquier cosa en la tarjeta SD del dispositivo actual, incluso información de contacto, mensajes de texto, etc. Bien, echemos un vistazo a cómo ocurrió este error.
1. WebView agrega un objeto JavaScript y la aplicación actual tiene permiso para leer y escribir tarjetas SD, es decir: android.permission.WRITE_EXTERNAL_STORAGE
2. En JS, puede atravesar el objeto de la ventana para encontrar el objeto con el método getClass, luego obtener el objeto Runtime a través del mecanismo de reflexión y luego llamar al método estático para ejecutar algunos comandos, como los comandos para acceder a archivos.
3. Luego, obtenga la cadena del flujo de entrada devuelta después de ejecutar el comando, y podrá obtener la información del nombre del archivo. Entonces puedes hacer lo que quieras, es muy peligroso. El código JS principal es el siguiente:
función ejecutar (cmdArgs) { para (var obj en la ventana) { si (getClass en la ventana [obj]) { alerta (obj) devolver ventana [obj].getClass().forName(java.lang.Runtime) .getMethod( getRuntime,null).invoke(null,null).exec(cmdArgs); Solución: 1. Sistema Android 4.2 o superiorEn Android 4.2 y superiores, Google realizó una corrección al declarar @JavascriptInterface en el método remoto de Java, como se muestra en el siguiente código:
clase JsObject { @JavascriptInterface public String toString() { return injectionObject; } } webView.addJavascriptInterface(new JsObject(), injectionObject(, text/html, null); toString())); 2. Sistemas inferiores a Android 4.2Este problema es más difícil de solucionar, pero no imposible.
En primer lugar, definitivamente ya no podemos llamar al método addJavascriptInterface. Respecto a este tema, lo más importante es conocer la acción del evento JS. Sabemos que existen los siguientes tipos de interacción entre JS y Java, como aviso, alerta, etc.
Dichas acciones corresponderán a los métodos correspondientes en la clase WebChromeClient. Para el aviso, su método correspondiente es el método onJsPrompt. La declaración de este método es la siguiente:
onJsPrompt booleano público (vista WebView, URL de cadena, mensaje de cadena, valor predeterminado de cadena, resultado de JsPromptResult)
A través de este método, JS puede pasar información (texto) a Java, y Java también puede pasar información (texto) a JS. ¿Podemos encontrar una solución a esta idea?
Después de algunas pruebas y análisis, encontramos una solución más factible. Consulte los siguientes puntos:
[1] Deje que JS llame a un método Javascript. En este método, se llama al método de solicitud y la información en JS se pasa a través de la solicitud. Esta información debe ser un texto significativo que combinamos, que puede incluir: identificadores específicos y nombres de métodos. , parámetros, etc.
En el método onJsPrompt, analizamos el texto pasado para obtener el nombre del método, los parámetros, etc., y luego llamamos al método especificado a través del mecanismo de reflexión para llamar al método del objeto Java.
[2] Con respecto al valor de retorno, puede devolverlo mediante el mensaje, de modo que los resultados del procesamiento del método en Java puedan devolverse a Js.
[3] Necesitamos generar dinámicamente un script JS que declare el método Javascript, cargarlo a través de loadUrl y registrarlo en la página html. El código específico es el siguiente:
javascript:(función JsAddJavascriptInterface_(){ if (typeof(window.jsInterface)!='undefinido') { console.log('window.jsInterface_js_interface_name existe!!');} else { window.jsInterface = { onButtonClick:function( arg0) {regresar Prompt('MiAplicación:'+JSON.stringify({obj:'jsInterface',func:'onButtonClick',args:[arg0]}) }, onImageClick:function(arg0,arg1,arg2) { Prompt('MiAplicación:'+JSON.stringify({obj:'jsInterface',func:'onImageClick',args:[arg0,arg1,arg2]}) }, } } } )());ilustrar:
1. JsInterface en el código anterior es el nombre del objeto que se registrará. Registra dos métodos, onButtonClick (arg0) y onImageClick (arg0, arg1, arg2). Si hay un valor de retorno, agregue return.
2. El mensaje es la cadena que acordamos, que contiene el identificador específico MyApp:, seguido de una cadena de cadenas JSON, que incluye nombres de métodos, parámetros, nombres de objetos, etc.
3. Cuando JS llama a onButtonClick o onImageClick, volverá a llamar al método onJsPrompt en la capa Java. Luego analizamos el nombre del método, los parámetros, el nombre del objeto y luego llamamos al método de manera reflexiva.
4. window.jsInterface significa que se declara un objeto Js en la ventana. La forma del método declarado es: nombre del método: función (parámetro 1, parámetro 2).
3. Interacción entre java y js en html51), Método 1:
mWebView.getSettings().setJavaScriptEnabled(true);mWebView.addJavascriptInterface(this, xxx);
Luego implemente el siguiente método en la clase actual:
@JavascriptInterface callback public voidFromH5(cadena final j) { //TODO }El nombre de callbackFromH5 debe ser el mismo que el nombre del método js en la página web.
Java llama al método js:
mWebView.loadUrl(String.format(javascript:java2js(0)));//Aquí está el JS para llamar a webview en el lado de Java
El nombre del método js debe ser coherente con la página web.
2) Método dos:
método jsbridge (https://github.com/lzyzsd/JsBridge)
Android JsBridge es una herramienta auxiliar que se utiliza para construir un puente de comunicación (llamada) entre el código Java nativo y el código JavaScript de la aplicación de Android.
1 Introducir jsBridge.jar en nuestro proyecto
Estudio de Android:
repositorios { // ... maven { url https://jitpack.io } } dependencias { compilar 'com.github.lzyzsd:jsbridge:1.0.4' }2. Archivo de diseño
<?xml versión=1.0 codificación=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 > <!-- el botón demuestra la llamada web de Java --> <Botón android:id=@+id/botón android:layout_width=match_parent android:text=@string/button_name android:layout_height=dp /> <!-- webview demuestra llamadas web 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. código java
//Carga la página web del servidor webView.loadUrl(https://www.baidu.com); //Debe tener el mismo nombre que la función js. webView.registerHandler(submitFromWeb, new BridgeHandler() { @Override public void handler(String data, función CallBackFunction) { String str =datos html devueltos a java: + datos; makeText(MainActivity.this, str, LENGTH_SHORT).show() ; Log.i(TAG, controlador = enviarDesdeWeb, datos de la web = + función de datos.onCallBack( str +); , después del procesamiento de Java: + str.substring(,)); } }); // Simula el usuario para obtener la ubicación local Usuario = new User(); usuario. ubicación = ubicación; nombre de usuario = Bruce; webView.callHandler(functionInJs, new Gson().toJson(usuario), new CallBackFunction() { @Override public void onCallBack(String data) { makeText(MainActivity.this, la página web está obteniendo su información, LENGTH_SHORT).show(); webView.send(hello); webView.callHandler(functionInJs, datos de Java, new CallBackFunction() { @Override public void onCallBack(String data) { // TODO Código auxiliar del método generado automáticamente Log.i(TAG, datos de respuesta de js + datos); } }) ;llamada js
var str1 = document.getElementById(text1).value; var str2 = document.getElementById(text2).value; // Llama al método java local window.WebViewJavascriptBridge.callHandler( 'submitFromWeb', {'param': str}, función (respuestaData) { document.getElementById(show).innerHTML = enviar obtener datos de respuesta de java, datos = + datos de respuesta } ); //Registrar escucha de eventos document.addEventListener( 'WebViewJavascriptBridgeReady' , function() { callback(WebViewJavascriptBridge) }, false //Registra la función de devolución de llamada y llama a la función de inicialización connectWebViewJavascriptBridge(function(bridge) { al conectarse para la primera vez bridge.init(function(message, ResponseCallback) { console.log('JS recibió un mensaje', mensaje); var data = { 'Javascript Responde': '¡Wee!' }; console.log('JS respondiendo con', datos); internalHTML = (datos de Java: = + datos); var respuestaData = Javascript dice ¡De vuelta también! respuestaCallback(responseData }); })4. Acerca de la optimización de webView
1. Configurar el modo de caché de WebView
private void initWebView() { mWebView.getSettings().setJavaScriptEnabled(true); mWebView.getSettings().setRenderPriority(RenderPriority.HIGH); mWebView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT); Habilitar API de almacenamiento DOM Función mWebView.getSettings().setDomStorageEnabled(true); //Habilitar la función API de almacenamiento de base de datos mWebView.getSettings().setDatabaseEnabled(true); String cacheDirPath = getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME; getCacheDir().getAbsolutePath()+Constant.APP_DB_DIRNAME; Log.i(TAG, cacheDirPath=+cacheDirPath); //Establecer la ruta de caché de la base de datos mWebView.getSettings().setDatabasePath(cacheDirPath); mWebView.getSettings().setAppCachePath(cacheDirPath); //Habilitar la función de cachés de aplicaciones mWebView.getSettings().setAppCacheEnabled(true);2. Borrar caché
/** * Borrar caché de WebView*/ public void clearWebViewCache(){ //Borrar la base de datos de caché de Webview try { deleteDatabase(webview.db); } //Archivo de caché de WebView Archivo appCacheDir = new File(getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME); Log.e(TAG, ruta appCacheDir=+appCacheDir.getAbsolutePath()); Archivo webviewCacheDir = nuevo Archivo(getCacheDir().getAbsolutePath()+/webviewCache(TAG, ruta webviewCacheDir=+webviewCacheDir.getAbsolutePath()); ); //Eliminar vista web Directorio de caché if(webviewCacheDir.exists()){ deleteFile(webviewCacheDir } //Eliminar directorio de caché de webview if(appCacheDir.exists()){ deleteFile(appCacheDir);3. Cuando se utiliza WebView para cargar páginas web, algunos archivos de recursos fijos como js/css/images y otros recursos serán relativamente grandes. Si se cargan directamente desde la red, la página se cargará más lentamente y consumirá más tráfico. Por lo tanto, estos archivos deben colocarse en activos y empaquetarse con la aplicación.
Para resolver este problema, utilice la función shouldInterceptRequest (vista WebView, URL de cadena) proporcionada por API 11 (HONEYCOMB) para cargar recursos locales.
API 21 volvió a desaprobar este método y sobrecargó un nuevo mustInterceptRequest. Los parámetros requeridos reemplazaron la URL con la solicitud.
Por ejemplo, hay una imagen xxxxx.png. Esta imagen se ha colocado en activos. Ahora que se carga un HTML externo, la imagen en activos debe sacarse y cargarse directamente sin volver a obtenerla de la red. Por supuesto, puedes cambiar el enlace de la imagen en html a file:///android_asset/xxxxx.png,
Pero este html no se puede compartir en Android, ios y WAP.
webView.setWebViewClient(new WebViewClient() { @Override public WebResourceResponse deberíaInterceptRequest(vista WebView, URL de cadena) { WebResourceResponse respuesta = nulo; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){ respuesta = super.shouldInterceptRequest(vista ,url); si (url.contiene(xxxxx.png)){ intentar { respuesta = new WebResourceResponse(image/png,UTF-8,getAssets().open(xxxxx.png)); catch (IOException e) { e.printStackTrace() } } } // return super.shouldInterceptRequest(view; , url); respuesta de retorno; } @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public WebResourceResponse deberíaInterceptRequest (vista WebView, solicitud WebResourceRequest) { respuesta WebResourceResponse = nulo; respuesta = super.shouldInterceptRequest (ver, solicitud) { prueba { respuesta = nuevo WebResourceResponse(image/png,UTF); -,getAssets().open(xxxxx.png)); } captura (IOException e) { e.printStackTrace(); } } devolver respuesta;Lo anterior es el contenido completo de este artículo. Espero que sea útil para el estudio de todos. También espero que todos apoyen VeVb Wulin Network.