Muitos APPs agora possuem páginas HTML5 incorporadas, como aquelas que mudam frequentemente. Algumas páginas requerem Java nativo para interagir com js em HTML5.
1. Sobre cookies HTML5Muitos parâmetros, como informações do usuário, podem ser usados em páginas da web. Você pode colocar essas informações em cookies antecipadamente. Você pode usar os seguintes métodos:
public static void addCookies (contexto de contexto, WebView webView, String url) { String url=https://www.xxxx.com/xx/xx/ String protocol = ; String autoridade = ; ; protocolo = urlObj.getProtocol() autoridade = urlObj.getAuthority(); webView.getSettings().getUserAgentString(); webView.getSettings().setUserAgentString(Constant.PROJECT_NAME + / + ParamHandler.getVersion(context) + ( + ua + ; HFWSH)); !TextUtils.isEmpty(protocolo) && !TextUtils.isEmpty(autoridade)) { if (protocol.equals(https) && autoridade.indexOf(liepin.com) > -1) { CookieSyncManager.createInstance(context); (verdadeiro); tente {List<String> dados = getCookiesString(); (!ListUtils.isEmpty(data)) { for (String valor: dados) { cookieManager.setCookie(url, valor } } cookieManager.setCookie(url, client_id= + Constant.CLIENT_ID + ;path=/;domain=. XXXX.com); cookieManager.setCookie(url, appVersion= + Constante .VERSION + ;caminho=/;domínio=.XXXX.com); CookieSyncManager.getInstance().sync(); } catch (Exceção e) { LogUtils.e(Exceção: + e.getMessage());
public List<String> getCookiesString() { ArrayList data = new ArrayList(); this.clearExpired() valores da coleção = this.mCookies.values(); () ) { SwiftCookie c = (SwiftCookie)var3.next(); data.add(c.toCookieString() } retornar dados; }
Adicione um cookie antes de mWebView.loadUrl(Url) e a página da web poderá obter o valor do parâmetro correspondente por meio do cookie.
2. Em relação às questões de segurança do jsjs tinha vulnerabilidades antes da versão 4.2
Através do JavaScript, você pode acessar qualquer coisa no cartão SD do dispositivo atual, até mesmo informações de contato, mensagens de texto, etc. Ok, vamos dar uma olhada em como esse erro ocorreu.
1. WebView adiciona um objeto JavaScript, e o aplicativo atual tem permissão para ler e gravar SDCard, ou seja: android.permission.WRITE_EXTERNAL_STORAGE
2. Em JS, você pode percorrer o objeto window para encontrar o objeto com o método getClass e, em seguida, obter o objeto Runtime por meio do mecanismo de reflexão e, em seguida, chamar o método estático para executar alguns comandos, como comandos para acessar arquivos.
3. Em seguida, obtenha a string do fluxo de entrada retornada após a execução do comando e você poderá obter as informações do nome do arquivo. Então você pode fazer o que quiser, é muito perigoso. O código JS principal é o seguinte:
function execute(cmdArgs) { for (var obj na janela) { if (getClass na janela[obj]) { alert(obj); return window[obj].getClass().forName(java.lang.Runtime) .getMethod( getRuntime,null).invoke(null,null).exec(cmdArgs);Solução: 1. Sistema Android 4.2 ou superior
No Android 4.2 e superior, o Google fez uma correção declarando @JavascriptInterface no método remoto do Java, conforme mostrado no código a seguir:
class JsObject { @JavascriptInterface public String toString() { return injectedObject; } webView.addJavascriptInterface(new JsObject(), injectedObject). toString()));2. Sistemas abaixo do Android 4.2
Este problema é mais difícil de resolver, mas não é impossível.
Primeiro de tudo, definitivamente não podemos mais chamar o método addJavascriptInterface. Em relação a esse assunto, o mais importante é conhecer a ação do evento JS. Sabemos que existem os seguintes tipos de interação entre JS e Java, como prompt, alerta, etc.
Tais ações corresponderão aos métodos correspondentes na classe WebChromeClient. Para prompt, seu método correspondente é o método onJsPrompt.
public boolean onJsPrompt (visualização WebView, String url, String mensagem, String defaultValue, resultado JsPromptResult)
Através deste método, JS pode passar informações (texto) para Java, e Java também pode passar informações (texto) para JS. Podemos encontrar uma solução para essa ideia?
Após alguns testes e análises, encontramos uma solução mais viável. Consulte os seguintes pontos:
[1] Deixe JS chamar um método Javascript. Neste método, o método prompt é chamado e as informações em JS são passadas por meio do prompt. Essas informações devem ser um texto significativo que combinamos, que pode incluir: identificadores específicos, nomes de métodos. , parâmetros, etc.
No método onJsPrompt, analisamos o texto passado para obter o nome do método, parâmetros, etc. e, em seguida, chamamos o método especificado por meio do mecanismo de reflexão para chamar o método do objeto Java.
[2] Quanto ao valor de retorno, você pode retorná-lo através de prompt, para que os resultados do processamento do método em Java possam ser retornados para Js.
[3] Precisamos gerar dinamicamente um script JS que declare o método Javascript, carregá-lo por meio de loadUrl e registrá-lo na página html.
javascript:(função JsAddJavascriptInterface_(){ if (typeof(window.jsInterface)!='indefinido') { console.log('window.jsInterface_js_interface_name existe!!');} else { window.jsInterface = { onButtonClick:function( arg0) { retorno 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]}));
ilustrar:
1. O jsInterface no código acima é o nome do objeto a ser registrado. Ele registra dois métodos, onButtonClick(arg0) e onImageClick(arg0, arg1, arg2).
2. O prompt é a string que combinamos, que contém o identificador específico MyApp:, seguido por uma string de strings JSON, que inclui nomes de métodos, parâmetros, nomes de objetos, etc.
3. Quando JS chama onButtonClick ou onImageClick, ele chama de volta o método onJsPrompt na camada Java. Em seguida, analisamos o nome do método, os parâmetros, o nome do objeto e, em seguida, chamamos o método de forma reflexiva.
4. window.jsInterface significa que um objeto Js é declarado na janela. A forma do método declarado é: nome do método: função (parâmetro 1, parâmetro 2).
3. Interação entre java e js em html51), Método 1:
mWebView.getSettings().setJavaScriptEnabled(true);mWebView.addJavascriptInterface(this, xxx);
Em seguida, implemente o seguinte método na classe atual:
@JavascriptInterface public void callbackFromH5(final String j) { //TODO }
O nome de callbackFromH5 deve ser igual ao nome do método js na página da web
Java chama o método js:
mWebView.loadUrl(String.format(javascript:java2js(0)));//Aqui está o JS para chamar webview no lado java
O nome do método js precisa ser consistente com a página da web
2) Método dois:
método jsbridge (https://github.com/lzyzsd/JsBridge)
Android JsBridge é uma ferramenta auxiliar usada para construir uma ponte de comunicação (chamada) entre o código java nativo e o código javascript do aplicativo Android.
1 Introduzir jsBridge.jar em nosso projeto
Estúdio Android:
repositórios { // ... maven { url https://jitpack.io } } dependências { compile 'com.github.lzyzsd:jsbridge:1.0.4' }
2. Arquivo de layout
<?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 demonstra Java chamando web --> <Button android:id=@+id/button android:layout_width=match_parent android:text=@string/button_name android:layout_height=dp /> <!-- webview demonstra chamada na 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
//Carrega a página do servidor webView.loadUrl(https://www.baidu.com); //Deve ter o mesmo nome da função js. webView.registerHandler(submitFromWeb, new BridgeHandler() { @Override public void handler(String data, função CallBackFunction) { String str =dados html retornados para java: + data; makeText(MainActivity.this, str, LENGTH_SHORT).show( ) ;Log.i(TAG, manipulador = submitFromWeb, dados da web = + dados); , após o processamento Java: + str.substring() } }); //Simular o usuário para obter a localização local User = new User(); usuário.localização = localização; user.name = Bruce; webView.callHandler(functionInJs, new Gson().toJson(usuário), new CallBackFunction() { @Override public void onCallBack(String data) { makeText(MainActivity.this, a página da web está obtendo suas informações, LENGTH_SHORT).show() } });
webView.callHandler(functionInJs, dados de Java, new CallBackFunction() { @Override public void onCallBack(String data) { // TODO stub de método gerado automaticamente Log.i(TAG, dados de resposta de js + data); } }) ;
chamada js
var str1 = document.getElementById(text1).value; var str2 = document.getElementById(text2).value; //Chame o método java local window.WebViewJavascriptBridge.callHandler( 'submitFromWeb' , {'param': str} , function (responseData) { document.getElementById(show).innerHTML = enviar obter responseData de java, data = + responseData } ); //Registra a escuta do evento document.addEventListener( 'WebViewJavascriptBridgeReady' , function() { callback(WebViewJavascriptBridge) }, false ); //Registra a função de retorno de chamada e chama a função de inicialização connectWebViewJavascriptBridge(function(bridge) { ao conectar para a primeira vez bridge.init(function(message, responseCallback) { console.log('JS recebeu uma mensagem', mensagem); var data = { 'Javascript Responde': 'Wee!' }; console.log('JS respondendo com', data)); innerHTML = (dados de Java: = + data var responseData = Javascript diz de volta, também conhecido como responseCallback (responseData }); })
4. Sobre a otimização do webView
1. Defina o modo de cache do WebView
private void initWebView() { mWebView.getSettings().setJavaScriptEnabled(true); mWebView.getSettings().setRenderPriority(RenderPriority.HIGH); Habilitar API de armazenamento DOM Function mWebView.getSettings().setDomStorageEnabled(true); //Ativar função API de armazenamento de banco de dados mWebView.getSettings().setDatabaseEnabled(true); getCacheDir().getAbsolutePath()+Constant.APP_DB_DIRNAME; Log.i(TAG, cacheDirPath=+cacheDirPath); //Definir o caminho do cache do banco de dados mWebView.getSettings().setDatabasePath(cacheDirPath); mWebView.getSettings().setAppCachePath(cacheDirPath); //Ativar função de caches de aplicativos mWebView.getSettings().setAppCacheEnabled(true);
2. Limpe o cache
/** * Limpar cache do WebView*/ public void clearWebViewCache(){ //Limpar banco de dados de cache do Webview try { deleteDatabase(webview.db); } //Arquivo de cache do WebView Arquivo appCacheDir = new File(getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME); Log.e(TAG, appCacheDir path=+appCacheDir.getAbsolutePath()); Arquivo webviewCacheDir = new File(getCacheDir().getAbsolutePath()+/webviewCache(TAG, webviewCacheDir path=+webviewCacheDir.getAbsolutePath()); ); //Excluir visualização da web Diretório de cache if(webviewCacheDir.exists()){ deleteFile(webviewCacheDir } //Excluir diretório de cache do webview if(appCacheDir.exists()){ deleteFile(appCacheDir);
3. Ao usar o WebView para carregar páginas da web, alguns arquivos de recursos fixos, como js/css/images e outros recursos, serão relativamente grandes. Se forem carregados diretamente da rede, a página carregará mais lentamente e consumirá mais tráfego. Portanto, esses arquivos devem ser colocados em ativos e empacotados com o aplicativo.
Para resolver esse problema, use a função shouldInterceptRequest(WebView view, String url) fornecida pela API 11 (HONEYCOMB) para carregar recursos locais.
A API 21 tornou obsoleto esse método novamente e sobrecarregou um novo shouldInterceptRequest. Os parâmetros necessários substituíram url por request.
Por exemplo, há uma imagem xxxxx.png. Esta imagem foi colocada em ativos. Agora que um HTML externo foi carregado, a imagem em ativos precisa ser retirada e carregada diretamente, sem obtê-la novamente da rede. Claro, você pode alterar o link da imagem em HTML para file:///android_asset/xxxxx.png,
Mas este html não pode ser compartilhado em Android, iOS e WAP.
webView.setWebViewClient (new WebViewClient () { @Override public WebResourceResponse shouldInterceptRequest (visualização WebView, URL de string) { resposta WebResourceResponse = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){ resposta = super.shouldInterceptRequest (ver ,url); if (url.contains(xxxxx.png)){tente {response = new WebResourceResponse(image/png,UTF-8,getAssets().open(xxxxx.png)); catch (IOException e) { e.printStackTrace(); , url); retornar resposta } @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public; WebResourceResponse shouldInterceptRequest (visualização WebView, solicitação WebResourceRequest) { resposta WebResourceResponse = null; resposta = super.shouldInterceptRequest (visualização, solicitação); -,getAssets().open(xxxxx.png)); catch (IOException e) { e.printStackTrace();
O texto acima é todo o conteúdo deste artigo. Espero que seja útil para o estudo de todos. Também espero que todos apoiem a Rede VeVb Wulin.