WebSettings
WebSettings mSettings = this.getSettings();
1、JavaScript设置
开启javascript:h5页要一般都有js,设置为true才允许h5页面执行js,但开启js非常耗内存,经常会导致oom,为了解决这个问题,可以在onstart方法中开启,在onStop中关闭。
mSettings.setJavaScriptEnabled(true);
但对于调用手机文件选择的,即使开启了js,也不一定拿得到文件路径。h5想要获取手机的文件,首先需要打开文件选择器,但是不同的android版本,js和native交互的方式不一样;而且在5.0发布后,回调的不是openFileChooser方法,而是onShowFileChooser方法,并且上文提到的ValueCallback参数里包裹着不再是Uri,而是Uri数组。因此,我们需要继承WebChromeClient,给不同的版本做相应的处理。
// For Android 3.0以下
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
if (mContext instanceof Activity) {
((Activity) mContext).startActivityForResult(Intent.createChooser(i, "Image Chooser"), FILECHOOSER_RESULTCODE);
}
}
// For Android 3.0+
public void openFileChooser(ValueCallback uploadMsg, String acceptType) {
openFileChooser(uploadMsg);
}
//For Android 4.1+
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
openFileChooser(uploadMsg);
}
// android 5.0+
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
if (mFilePathCallback != null) {
mFilePathCallback.onReceiveValue(null);
}
mFilePathCallback = filePathCallback;
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(mContext.getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath);
} catch (Exception ex) {
// Error occurred while creating the File
ex.printStackTrace();
}
// Continue only if the File was successfully created
if (photoFile != null) {
mCameraPhotoPath = "file:" + photoFile.getAbsolutePath();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
} else {
takePictureIntent = null;
}
}
Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
contentSelectionIntent.setType("image/*");
Intent[] intentArray;
if (takePictureIntent != null) {
intentArray = new Intent[]{takePictureIntent};
} else {
intentArray = new Intent[0];
}
Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
if (mContext instanceof Activity) {
((Activity) mContext).startActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE);
}
return true;
}
@SuppressLint("SdCardPath")
private File createImageFile() {
//mCameraPhotoPath="/mnt/sdcard/tmp.png";
File file = new File(Environment.getExternalStorageDirectory() + "/", "tmp.png");
mCameraPhotoPath = file.getAbsolutePath();
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
return file;
}
我们知道,从activity打开文件选择器,文件信息是在onActivityResult里返回来了,因为在5.0发布后,ValueCallback参数里包裹着不再是Uri,而是Uri数组。所以在给h5回调的时候还需要给5.0+做相应的回调。
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == FILECHOOSER_RESULTCODE && mUploadMessage != null) {
Uri result = null;
if (resultCode == Activity.RESULT_OK && data != null) {
result = data.getData();
if (result != null) {
String imagePath = ImagePathUtil.getPath(mContext, result);
if (!TextUtils.isEmpty(imagePath)) {
result = Uri.parse("file:///" + imagePath);
}
}
}
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
} else if (requestCode == INPUT_FILE_REQUEST_CODE && mFilePathCallback != null) {
// 5.0的回调
Uri[] results = null;
// Check that the response is a good one
if (resultCode == Activity.RESULT_OK) {
if (data == null) {
// If there is not data, then we may have taken a photo
if (mCameraPhotoPath != null) {
results = new Uri[]{Uri.parse(mCameraPhotoPath)};
}
} else {
String dataString = data.getDataString();
if (dataString != null) {
results = new Uri[]{Uri.parse(dataString)};
}
}
}
mFilePathCallback.onReceiveValue(results);
mFilePathCallback = null;
}
}
2、Dom
开启本地DOM存储。应该是Html 5中的localStorage(可以使用Android4.4手机和Chrome Inspcet Device联调),用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的,绝大多数的浏览器都是支持 localStorage 的,但是鉴于它的安全特性(任何人都能读取到它,尽管有相应的限制,将敏感数据存储在这里依然不是明智之举),Android 默认是关闭该功能的。
//Sets whether the DOM storage API is enabled. The default value is false.
mSettings.setDomStorageEnabled(true);//开启DOM
3、音视频自动播放
在打开一个h5页面时,如果h5页面需要自动播放一个音视频时,为了在android端能够自动播放,h5需要在js中调用autoPlay方法来播放多媒体,但是在android4.2以后版本,对于这种非用户手势促发的播放,默认是不允许的。
// 设置4.2以后版本支持autoPlay,非用户手势促发
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
mSettings.setMediaPlaybackRequiresUserGesture(false);
}
4、混合内容
Mixed Content问题发生在HTTPS页面中通过HTTP方式引用资源。
对于安卓,WebView有配置可以设定Mixed Content的行为。
产生这种行为的原因是在安卓21之前,这种行为默认是被允许的,而21之后,Mixed Content被视为不安全的行为被默认禁止。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
5、userAgent
userAgent 属性是一个只读的字符串,声明了浏览器用于 HTTP 请求的用户代理头的值。
mSettings.setUserAgentString(mSettings.getUserAgentString() + " QLChat/" + VersionInfoUtil.getVersionCode());
6、开启debug
有时候需要调试webview页面,但在android4.4以后,默认就不允许了。
//Enables debugging of web contents (HTML / CSS / JavaScript)
if (BuildConfig.DEVELOPMENT_ENV) {
setWebContentsDebuggingEnabled(true);
}
7、其它设置
//设置字符编码
mSettings.setDefaultTextEncodingName("utf-8");
//设置web页面
mSettings.setAllowFileAccess(true);//设置支持文件流
mSettings.setSupportZoom(false);// 支持缩放
mSettings.setBuiltInZoomControls(false);// 支持缩放
mSettings.setUseWideViewPort(true);// 调整到适合webview大小
mSettings.setLoadWithOverviewMode(true);// 调整到适合webview大小
mSettings.setDefaultZoom(WebSettings.ZoomDensity.FAR);// 屏幕自适应网页,如果没有这个,在低分辨率的手机上显示可能会异常
mSettings.setRenderPriority(WebSettings.RenderPriority.HIGH);
//提高网页加载速度,暂时阻塞图片加载,然后网页加载好了,在进行加载图片
mSettings.setBlockNetworkImage(true);
mSettings.setAppCacheEnabled(false);//开启缓存机制