De nombreuses applications contiennent désormais des pages HTML5, telles que celles qui changent fréquemment. Certaines pages nécessitent Java natif pour interagir avec js en HTML5. Voici une introduction à l'utilisation de HTML5 dans Android :
1. À propos des cookies HTML5De nombreux paramètres tels que les informations utilisateur peuvent être utilisés dans les pages Web. Vous pouvez placer ces informations dans des cookies au préalable. Vous pouvez utiliser les méthodes suivantes :
public static void addCookies (Contexte contextuel, WebView webView, String url) { String url=https://www.xxxx.com/xx/xx/ String protocol = ; String Authority = ; ; protocole = urlObj.getProtocol(); autorité = urlObj.getAuthority(); } catch (Exception e) { e.printStackTrace( } String ua = webView.getSettings().getUserAgentString(); webView.getSettings().setUserAgentString(Constant.PROJECT_NAME + / + ParamHandler.getVersion(context) + ( + ua + ; HFWSH)); !TextUtils.isEmpty(protocole) && !TextUtils.isEmpty(authority)) { if (protocol.equals(https) && authority.indexOf(liepin.com) > -1) { CookieSyncManager.createInstance(context); (vrai); essayez { 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= + Constante .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(); Valeurs de collection = this.mCookies.values(); () ) { SwiftCookie c = (SwiftCookie)var3.next(); data.add(c.toCookieString() ); }Ajoutez un cookie avant mWebView.loadUrl(Url) et la page Web peut obtenir la valeur du paramètre correspondante via le cookie.
2. Concernant les problèmes de sécurité de jsjs avait des vulnérabilités avant 4.2
Grâce à JavaScript, vous pouvez accéder à tout ce qui se trouve sur la carte SD de l'appareil actuel, même aux informations de contact, aux messages texte, etc. Ok, regardons comment cette erreur s'est produite.
1. WebView ajoute un objet JavaScript et l'application actuelle a l'autorisation de lire et d'écrire la carte SD, c'est-à-dire : android.permission.WRITE_EXTERNAL_STORAGE
2. Dans JS, vous pouvez parcourir l'objet window pour trouver l'objet avec la méthode getClass, puis obtenir l'objet Runtime via le mécanisme de réflexion, puis appeler la méthode statique pour exécuter certaines commandes, telles que les commandes d'accès aux fichiers.
3. Récupérez ensuite la chaîne du flux d'entrée renvoyée après l'exécution de la commande et vous pourrez obtenir les informations sur le nom du fichier. Après, tu peux faire ce que tu veux, c'est tellement dangereux. Le code JS de base est le suivant :
function exécuter(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); Solution: 1. Système Android 4.2 ou supérieurSous Android 4.2 et supérieur, Google a apporté une correction en déclarant un @JavascriptInterface sur la méthode distante de Java, comme indiqué dans le code suivant :
class JsObject { @JavascriptInterface public String toString() { return injectedObject; } } webView.addJavascriptInterface(new JsObject(), injectedObject); webView.loadData(, text/html, null); toString())); 2. Systèmes inférieurs à Android 4.2Ce problème est plus difficile à résoudre, mais il n’est pas impossible.
Tout d’abord, nous ne pouvons définitivement plus appeler la méthode addJavascriptInterface. Concernant ce problème, le plus important est de connaître l'action de l'événement JS. Nous savons qu'il existe les types d'interaction suivants entre JS et Java, tels que l'invite, l'alerte, etc.
De telles actions correspondront aux méthodes correspondantes dans la classe WebChromeClient. Pour prompt, sa méthode correspondante est la méthode onJsPrompt. La déclaration de cette méthode est la suivante :
public boolean onJsPrompt (vue WebView, URL de chaîne, message de chaîne, valeur par défaut de chaîne, résultat JsPromptResult)
Grâce à cette méthode, JS peut transmettre des informations (texte) à Java, et Java peut également transmettre des informations (texte) à JS. Pouvons-nous trouver une solution à cette idée ?
Après quelques essais et analyses, nous avons trouvé une solution plus réalisable. Veuillez consulter les points suivants :
[1] Laissez JS appeler une méthode Javascript. Dans cette méthode, la méthode d'invite est appelée et les informations dans JS sont transmises via l'invite. Ces informations doivent être un texte significatif que nous combinons, qui peut inclure : des identifiants spécifiques, des noms de méthode. , paramètres, etc.
Dans la méthode onJsPrompt, nous analysons le texte transmis pour obtenir le nom de la méthode, les paramètres, etc., puis appelons la méthode spécifiée via le mécanisme de réflexion pour appeler la méthode de l'objet Java.
[2] Concernant la valeur de retour, vous pouvez la renvoyer via une invite, afin que les résultats du traitement de la méthode en Java puissent être renvoyés à Js.
[3] Nous devons générer dynamiquement un script JS qui déclare la méthode Javascript, le charger via loadUrl et l'enregistrer dans la page html. Le code spécifique est le suivant :
javascript:(function JsAddJavascriptInterface_(){ if (typeof(window.jsInterface)!='undefined') { console.log('window.jsInterface_js_interface_name existe !!');} else { window.jsInterface = { onButtonClick:function( arg0) {retour prompt('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onButtonClick',args:[arg0]}) }, onImageClick:function(arg0,arg1,arg2) { prompt('MonApp:'+JSON.stringify({obj:'jsInterface',func:'onImageClick',args:[arg0,arg1,arg2]}));illustrer:
1. Le jsInterface dans le code ci-dessus est le nom de l'objet à enregistrer. Il enregistre deux méthodes, onButtonClick(arg0) et onImageClick(arg0, arg1, arg2).
2. L'invite est la chaîne sur laquelle nous nous sommes mis d'accord, qui contient l'identifiant spécifique MyApp :, suivi d'une chaîne de chaînes JSON, qui inclut les noms de méthodes, les paramètres, les noms d'objets, etc.
3. Lorsque JS appelle onButtonClick ou onImageClick, il rappelle la méthode onJsPrompt dans la couche Java. Nous analysons ensuite le nom de la méthode, les paramètres, le nom de l'objet, puis appelons la méthode de manière réfléchie.
4. window.jsInterface signifie qu'un objet Js est déclaré sur la fenêtre. La forme de la méthode déclarée est : nom de la méthode : fonction (paramètre 1, paramètre 2).
3. Interaction entre Java et js en html51), Méthode 1 :
mWebView.getSettings().setJavaScriptEnabled(true);mWebView.addJavascriptInterface(this, xxx);
Implémentez ensuite la méthode suivante dans la classe actuelle :
@JavascriptInterface public void callbackFromH5(final String j) { //TODO }Le nom de callbackFromH5 doit être le même que le nom de la méthode js dans la page Web
Java appelle la méthode js :
mWebView.loadUrl(String.format(javascript:java2js(0)));//Voici le JS pour appeler webview côté java
Le nom de la méthode js doit être cohérent avec la page Web
2) Deuxième méthode :
méthode jsbridge (https://github.com/lzyzsd/JsBridge)
Android JsBridge est un outil auxiliaire utilisé pour créer un pont de communication (appel) entre le code Java natif et le code javascript de l'application Android.
1 Introduisez jsBridge.jar dans notre projet
AndroidStudio :
dépôts { // ... maven { url https://jitpack.io } } dépendances { compile 'com.github.lzyzsd:jsbridge:1.0.4' }2. Fichier de mise en page
<?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 > Le bouton <!-- illustre l'appel Web Java --> <Button android:id=@+id/button android:layout_width=match_parent android:text=@string/button_name android:layout_height=dp /> <!-- webview démontre l'appel 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. code Java
//Charger la page Web du serveur webView.loadUrl(https://www.baidu.com); //Doit avoir le même nom que la fonction js. webView.registerHandler(submitFromWeb, new BridgeHandler() { @Override public void handler(String data, CallBackFunction function) { String str =données html renvoyées à java : + data; makeText(MainActivity.this, str, LENGTH_SHORT).show( ) ; Log.i(TAG, handler = submitFromWeb, données du web = + data function.onCallBack( str +); , après le traitement Java : + str.substring(,)); } }); //Simuler l'utilisateur pour obtenir l'emplacement local User user = new User location(); user.location = location; user.name = Bruce; webView.callHandler(functionInJs, new Gson().toJson(user), new CallBackFunction() { @Override public void onCallBack(String data) { makeText(MainActivity.this, la page Web récupère vos informations, LENGTH_SHORT).show(); webView.send(hello); webView.callHandler(functionInJs, données de Java, new CallBackFunction() { @Override public void onCallBack(String data) { // TODO Stub de méthode généré automatiquement Log.i(TAG, données de réponse de js + data); } }) ;appel js
var str1 = document.getElementById(text1).value; var str2 = document.getElementById(text2).value; //Appelle la méthode java locale window.WebViewJavascriptBridge.callHandler( 'submitFromWeb' , {'param': str} , function (responseData) { document.getElementById(show).innerHTML = envoyer récupérer les données de réponse de Java, data = + ResponseData } ); //Enregistrer l'événement d'écoute document.addEventListener( 'WebViewJavascriptBridgeReady' , function() { callback(WebViewJavascriptBridge) }, false ); //Enregistrer la fonction de rappel et appeler la fonction d'initialisation connectWebViewJavascriptBridge(function(bridge) { lors de la connexion pour la première fois bridge.init(function(message, réponseCallback) { console.log('JS a reçu un message', message); var data = { 'Javascript Répond : 'Wee !' } ; console.log('JS répondant avec', data); innerHTML = (données de Java : = + data); var réponseData = Javascript dit Right back aka !; })4. À propos de l'optimisation de webView
1. Définir le mode cache WebView
private void initWebView() { mWebView.getSettings().setJavaScriptEnabled(true); mWebView.getSettings().setRenderPriority(RenderPriority.HIGH); mWebView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT); Activer l'API de stockage DOM Function mWebView.getSettings().setDomStorageEnabled(true); //Activer la fonction API de stockage de base de données mWebView.getSettings().setDatabaseEnabled(true); String cacheDirPath = getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME; getCacheDir().getAbsolutePath()+Constant.APP_DB_DIRNAME; Log.i(TAG, cacheDirPath=+cacheDirPath); //Définir le chemin du cache de la base de données mWebView.getSettings().setDatabasePath(cacheDirPath); mWebView.getSettings().setAppCachePath(cacheDirPath); //Activer la fonction des caches d'application mWebView.getSettings().setAppCacheEnabled(true);2. Vider le cache
/** * Effacer le cache WebView*/ public void clearWebViewCache(){ //Effacer la base de données du cache Webview try { deleteDatabase(webview.db); deleteDatabase(webviewCache.db); catch (Exception e) { e.printStackTrace(); } //Fichier cache WebView Fichier appCacheDir = new File(getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME); Log.e (TAG, appCacheDir path=+appCacheDir.getAbsolutePath()); Fichier webviewCacheDir = new File(getCacheDir().getAbsolutePath()+/webviewCache); Log.e(TAG, webviewCacheDir path=+webviewCacheDir.getAbsolutePath()); ); //Supprimer la vue Web Répertoire de cache if(webviewCacheDir.exists()){ deleteFile(webviewCacheDir); } //Supprimer le répertoire de cache de vue Web if(appCacheDir.exists()){ deleteFile(appCacheDir);3. Lorsque vous utilisez WebView pour charger des pages Web, certains fichiers de ressources fixes tels que js/css/images et d'autres ressources seront relativement volumineux s'ils sont chargés directement depuis le réseau, la page se chargera plus lentement et consommera plus de trafic. Ces fichiers doivent donc être placés dans des actifs et emballés avec l'application.
Pour résoudre ce problème, utilisez la fonction ShouldInterceptRequest(WebView view, String url) fournie par l'API 11 (HONEYCOMB) pour charger les ressources locales.
L'API 21 a de nouveau rendu obsolète cette méthode et a surchargé un nouveau ShouldInterceptRequest. Les paramètres requis ont remplacé l'URL par la requête.
Par exemple, il y a une image xxxxx.png. Cette image a été placée dans les actifs. Maintenant qu'un code HTML externe est chargé, l'image dans les actifs doit être directement extraite et chargée sans la réobtenir du réseau. Bien sûr, vous pouvez modifier le lien de l'image en html en file:///android_asset/xxxxx.png,
Mais ce code HTML ne peut pas être partagé sur Android, iOS et WAP.
webView.setWebViewClient(new WebViewClient() { @Override public WebResourceResponse ShouldInterceptRequest(WebView view, String url) { WebResourceResponse réponse = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){ réponse = super.shouldInterceptRequest(view ,url); if (url.contains(xxxxx.png)){ essayer { réponse = new WebResourceResponse(image/png,UTF-8,getAssets().open(xxxxx.png)); } catch (IOException e) { e.printStackTrace(); } } // return super.shouldInterceptRequest(view) , url); renvoie la réponse ; } @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public WebResourceResponse ShouldInterceptRequest (vue WebView, requête WebResourceRequest) { Réponse WebResourceResponse = null; réponse = super.shouldInterceptRequest (view, request); if (url.contains (xxxxx.png)) { try { réponse = new WebResourceResponse (image/png, UTF -,getAssets().open(xxxxx.png)); } catch (IOException e) { e.printStackTrace(); } } renvoie la réponse ;Ce qui précède représente l’intégralité du contenu de cet article. J’espère qu’il sera utile à l’étude de chacun. J’espère également que tout le monde soutiendra le réseau VeVb Wulin.