1.基本适配设置
settings =getSettings();
settings.setJavaScriptEnabled(true);//支持js
settings.setUseWideViewPort(true);
settings.setLoadWithOverviewMode(true);
2.硬件加速 提高webview加载速度
if (Build.VERSION.SDK_INT >= 21) {
settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
setLayerType(View.LAYER_TYPE_HARDWARE, null);
} else if (Build.VERSION.SDK_INT >= 19) {
setLayerType(View.LAYER_TYPE_HARDWARE, null);
} else if (Build.VERSION.SDK_INT < 19) {
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
3.设置webview 安全性 一般上传应用会对apk进行安全扫描,有关webview的安全问题,可通过该方法解决
private void setWebViewSecurity(){
try {
removeJavascriptInterface("searchBoxJavaBridge_");
removeJavascriptInterface("accessibility");
removeJavascriptInterface("accessibilityTraversal");
getSettings().setSavePassword(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
} catch (Exception e) {
}
}
4.支持视频全屏播放方法,重写webChromeClient getVideoLoadingProgressView,onShowCustomView,onHideCustomView
三个方法。
原理是获取视频播放的view 然后创建父类容器view 加载到根view上显示出来
public class CommonWebChromeClient extends WebChromeClient{
/*** 视频播放相关的方法 **/
@Override
public View getVideoLoadingProgressView() {
if(videoWebFactory!=null){
return videoWebFactory.getVideoLoadingProgressView();
}
return null;
}
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
if(videoWebFactory!=null){
videoWebFactory.showCustomView(view, callback);
}
}
@Override
public void onHideCustomView() {
if(videoWebFactory!=null){
videoWebFactory.hideCustomView();
}
}
}
VideoWebFactory代码
public class VideoWebFactory {
/** 视频全屏参数 */
protected static final FrameLayout.LayoutParams COVER_SCREEN_PARAMS = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
private View customView;
private FrameLayout fullscreenContainer;
private WebChromeClient.CustomViewCallback customViewCallback;
private Context context;
private Window window;
private WebView webView;
public VideoWebFactory (Context context,WebView webView){
this.context =context;
this.window = ((Activity)context).getWindow();
this.webView = webView;
}
public View getVideoLoadingProgressView(){
FrameLayout frameLayout = new FrameLayout(context);
frameLayout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
return frameLayout;
}
/** 视频播放全屏 **/
public void showCustomView(View view, CustomViewCallback callback) {
// if a view already exists then immediately terminate the new one
if (customView != null) {
callback.onCustomViewHidden();
return;
}
window.getDecorView();
FrameLayout decor = (FrameLayout) window.getDecorView();
fullscreenContainer = new FullscreenHolder(context);
fullscreenContainer.addView(view, COVER_SCREEN_PARAMS);
decor.addView(fullscreenContainer, COVER_SCREEN_PARAMS);
customView = view;
setStatusBarVisibility(false);
customViewCallback = callback;
}
/** 隐藏视频全屏 */
public void hideCustomView() {
if (customView == null) {
return;
}
setStatusBarVisibility(true);
FrameLayout decor = (FrameLayout) window.getDecorView();
decor.removeView(fullscreenContainer);
fullscreenContainer = null;
customView = null;
customViewCallback.onCustomViewHidden();
webView.setVisibility(View.VISIBLE);
}
/** 全屏容器界面 */
private static class FullscreenHolder extends FrameLayout {
public FullscreenHolder(Context ctx) {
super(ctx);
setBackgroundColor(ctx.getResources().getColor(android.R.color.black));
}
@Override
public boolean onTouchEvent(MotionEvent evt) {
return true;
}
}
private void setStatusBarVisibility(boolean visible) {
int flag = visible ? 0 : WindowManager.LayoutParams.FLAG_FULLSCREEN;
window.setFlags(flag, WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
public View getCustomView() {
return customView;
}
}
4.支持文件上传
webview支持file文件上传,不过,对应有版本的区别,5.0以下的版本只能每次选择一个文件,5.0以上的版本支持多文件选择
(1)当触发上传文件选择的时候,webview会回调openFileChooser 方法并提供ValueCallback<Uri> mUM 作为文件上传提交对象(文件选择可以调用相关的库)
(2)最后在选择完文件之后,设置uri 对象,通过mUM.onReceiveValue(uri);进行文件提交。注意,如果没有选择文件,请设置mUM.onReceiveValue(null); 作为取消选择文件的操作,不然,webview将处于文件选择状态,web页面不能点击响应。
public class CommonWebChromeClient extends WebChromeClient{
/**
* 文件上传
* */
//For Android 3.0+
public void openFileChooser(ValueCallback<Uri> uploadMsg){
mUM = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
((Activity)context).startActivityForResult(Intent.createChooser(i,"File Chooser"), WebFileFactory.SELECT_PHOTO);
}
// For Android 3.0+, above method not supported in some android 3+ versions, in such case we use this
public void openFileChooser(ValueCallback uploadMsg, String acceptType){
mUM = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
((Activity)context).startActivityForResult(Intent.createChooser(i, "File Browser"),WebFileFactory.SELECT_PHOTO);
}
//For Android 4.1+ 只能选择一个文件
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
mUM = uploadMsg;
if(onFileSelected!=null){
onFileSelected.onSelectOne(mUM,mUMA);
}
if(webFileFactory!=null){
webFileFactory.setmUM(mUM);
webFileFactory.showPhotoSelectForOne();
}
}
//For Android 5.0+ 多个文件选择
public boolean onShowFileChooser(
WebView webView, ValueCallback<Uri[]> filePathCallback,
WebChromeClient.FileChooserParams fileChooserParams){
mUMA = filePathCallback;
if(onFileSelected!=null){
onFileSelected.onSelect(mUM,mUMA);
}
if(webFileFactory!=null){
webFileFactory.setmUMA(mUMA);
webFileFactory.showPhotoSelect();
}
return true;
}
webFileFactory为 图片选择 处理类
public class WebFileFactory {
private Context context;
private ValueCallback<Uri> mUM;
private ValueCallback<Uri[]> mUMA;
private Uri uri;
public static final int TAKE_PICTURE = 102;
public static final int SELECT_PHOTO = 103;
public static final int TAKE_VIDEO = 107;
public static final int SELECT_VIDEO = 106;
public static final int TAKE_PICTURE_ONE = 104;
public static final int SELECT_PHOTO_ONE = 105;
public static final int TAKE_VIDEO_ONE = 108;
public static final int SELECT_VIDEO_ONE = 109;
public WebFileFactory(Context context) {
this.context = context;
}
public void setmUM(ValueCallback<Uri> mUM) {
this.mUM = mUM;
}
public void setmUMA(ValueCallback<Uri[]> mUMA) {
this.mUMA = mUMA;
}
public void showPhotoSelectForOne() {
String[] datas = new String[] { "拍照", "录像", "相册", "视频" };
SheetView sheetView = new SheetView(context, datas);
sheetView.setLisenter(new SheetView.Lisenter() {
@Override
public void onSelect(int position) {
if (position == 1) {
uri = Uri.fromFile(new File(
FileUtils.getAppImageFilePath(context) + "/" + System.currentTimeMillis() + ".png"));
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, uri);
intent.putExtra("return-data", true);
((Activity) context).startActivityForResult(intent, WebFileFactory.TAKE_PICTURE_ONE);
} else if (position == 2) {
uri = Uri.fromFile(new File(
FileUtils.getAppImageFilePath(context) + "/" + System.currentTimeMillis() + ".mp4"));
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);// 创建一个请求视频的意图
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);// 设置视频的质量,值为0-1,
intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 60);// 设置视频的录制长度,s为单位
intent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, 20 * 1024 * 1024L);// 设置视频文件大小,字节为单位
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, uri);
((Activity) context).startActivityForResult(intent, WebFileFactory.TAKE_VIDEO_ONE);
} else if (position == 3) {
Intent intent = new Intent(context, SelectPhotoActivity.class);
intent.putExtra("max", 1);
((Activity) context).startActivityForResult(intent, WebFileFactory.SELECT_PHOTO_ONE);
} else if (position == 4) {
Intent i = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
((Activity) context).startActivityForResult(i, WebFileFactory.SELECT_VIDEO_ONE);
}
}
});
sheetView.show();
}
public void showPhotoSelect() {
String[] datas = new String[] { "拍照", "录像", "相册", "视频" };
SheetView sheetView = new SheetView(context, datas);
sheetView.setLisenter(new SheetView.Lisenter() {
@Override
public void onSelect(int position) {
if (position == 1) {
uri = Uri.fromFile(new File(
FileUtils.getAppImageFilePath(context) + "/" + System.currentTimeMillis() + ".png"));
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, uri);
intent.putExtra("return-data", true);
((Activity) context).startActivityForResult(intent, WebFileFactory.TAKE_PICTURE);
} else if (position == 2) {
uri = Uri.fromFile(new File(
FileUtils.getAppImageFilePath(context) + "/" + System.currentTimeMillis() + ".mp4"));
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);// 创建一个请求视频的意图
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);// 设置视频的质量,值为0-1,
intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 60);// 设置视频的录制长度,s为单位
intent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, 20 * 1024 * 1024L);// 设置视频文件大小,字节为单位
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, uri);
((Activity) context).startActivityForResult(intent, WebFileFactory.TAKE_VIDEO);
} else if (position == 3) {
Intent intent = new Intent(context, SelectPhotoActivity.class);
intent.putExtra("max", 9);
((Activity) context).startActivityForResult(intent, WebFileFactory.SELECT_PHOTO);
} else if (position == 4) {
Intent i = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
((Activity) context).startActivityForResult(i, WebFileFactory.SELECT_VIDEO);
} else {
if (mUMA != null) {
mUMA.onReceiveValue(null);
} else if (mUM != null) {
mUM.onReceiveValue(null);
}
}
}
});
sheetView.show();
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == TAKE_PICTURE_ONE || requestCode == TAKE_VIDEO_ONE) {
if (uri != null) {
mUM.onReceiveValue(uri);
}
} else if (requestCode == SELECT_PHOTO_ONE) {
if (data != null) {
Bundle bundle = data.getBundleExtra("bundle");
List<PhotoInfo> imgs = bundle.getParcelableArrayList("imgs");
Uri uri = Uri.parse(imgs.get(0).getPath_file());
mUM.onReceiveValue(uri);
} else {
if (mUMA != null) {
mUMA.onReceiveValue(null);
} else if (mUM != null) {
mUM.onReceiveValue(null);
}
}
} else if (requestCode == SELECT_VIDEO_ONE) {
if (data != null) {
Uri uri = data.getData();
Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
cursor.moveToFirst();
String path = "file://" + cursor.getString(1); // 视频文件路径
Uri uri_video = Uri.parse(path);
mUM.onReceiveValue(uri_video);
} else {
if (mUMA != null) {
mUMA.onReceiveValue(null);
} else if (mUM != null) {
mUM.onReceiveValue(null);
}
}
}
if (requestCode == TAKE_PICTURE || requestCode == TAKE_VIDEO) {
if (uri != null) {
Uri[] uris = new Uri[] { uri };
mUMA.onReceiveValue(uris);
}
} else if (requestCode == SELECT_PHOTO) {
if (data != null) {
Bundle bundle = data.getBundleExtra("bundle");
List<PhotoInfo> imgs = bundle.getParcelableArrayList("imgs");
Uri[] uris = new Uri[imgs.size()];
for (int i = 0; i < imgs.size(); i++) {
PhotoInfo photoInfo = imgs.get(i);
Uri uri = Uri.parse(photoInfo.getPath_file());
uris[i] = uri;
}
mUMA.onReceiveValue(uris);
} else {
if (mUMA != null) {
mUMA.onReceiveValue(null);
} else if (mUM != null) {
mUM.onReceiveValue(null);
}
}
} else if (requestCode == SELECT_VIDEO) {
if (data != null) {
Uri uri = data.getData();
Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
cursor.moveToFirst();
String path = "file://" + cursor.getString(1); // 视频文件路径
Uri uri_video = Uri.parse(path);
mUMA.onReceiveValue(new Uri[] { uri_video });
} else {
if (mUMA != null) {
mUMA.onReceiveValue(null);
} else if (mUM != null) {
mUM.onReceiveValue(null);
}
}
}
}
}
5.附上本人封装的CommonWebView以及使用方式
public class CommonWebView extends WebView{
private Context context;
private WebSettings settings;
private VideoWebFactory videoWebFactory;
private WebFileFactory webFileFactory;
private ValueCallback<Uri> mUM;
private ValueCallback<Uri[]> mUMA;
private OnFileSelected onFileSelected;
public CommonWebView(Context context) {
super(context);
this.context =context;
init();
}
public CommonWebView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context =context;
init();
}
public CommonWebView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context =context;
init();
}
private void init(){
//基础设置
settings =getSettings();
settings.setJavaScriptEnabled(true);
settings.setUseWideViewPort(true); // 关键点
settings.setLoadWithOverviewMode(true);
if (Build.VERSION.SDK_INT >= 21) {
settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
setLayerType(View.LAYER_TYPE_HARDWARE, null);
} else if (Build.VERSION.SDK_INT >= 19) {
setLayerType(View.LAYER_TYPE_HARDWARE, null);
} else if (Build.VERSION.SDK_INT < 19) {
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
//设置webview安全性
setWebViewSecurity();
setWebViewClient();
}
private void setWebViewClient(){
setWebViewClient(new CommonWebViewClient());
}
//支持视频播放
public void setSupportVideo(CommonWebChromeClient webChromeClient){
videoWebFactory = new VideoWebFactory(context,this);
setWebChromeClient(webChromeClient);
}
//文件上传
public CommonWebView setSupportFile(CommonWebChromeClient webChromeClient){
webFileFactory = new WebFileFactory(context);
settings.setAllowFileAccess(true);
setSupportVideo(webChromeClient);
return this;
}
public void setOnFileSelected(OnFileSelected onFileSelected) {
this.onFileSelected = onFileSelected;
}
public WebFileFactory getWebFileFactory() {
return webFileFactory;
}
public class CommonWebViewClient extends WebViewClient{
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
loadUrl(url);
return true;
}
}
public class CommonWebChromeClient extends WebChromeClient{
/*** 视频播放相关的方法 **/
@Override
public View getVideoLoadingProgressView() {
if(videoWebFactory!=null){
return videoWebFactory.getVideoLoadingProgressView();
}
return null;
}
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
if(videoWebFactory!=null){
videoWebFactory.showCustomView(view, callback);
}
}
@Override
public void onHideCustomView() {
if(videoWebFactory!=null){
videoWebFactory.hideCustomView();
}
}
/**
* 文件上传
* */
//For Android 3.0+
public void openFileChooser(ValueCallback<Uri> uploadMsg){
mUM = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
((Activity)context).startActivityForResult(Intent.createChooser(i,"File Chooser"), WebFileFactory.SELECT_PHOTO);
}
// For Android 3.0+, above method not supported in some android 3+ versions, in such case we use this
public void openFileChooser(ValueCallback uploadMsg, String acceptType){
mUM = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
((Activity)context).startActivityForResult(Intent.createChooser(i, "File Browser"),WebFileFactory.SELECT_PHOTO);
}
//For Android 4.1+ 只能选择一个文件
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
mUM = uploadMsg;
if(onFileSelected!=null){
onFileSelected.onSelectOne(mUM,mUMA);
}
if(webFileFactory!=null){
webFileFactory.setmUM(mUM);
webFileFactory.showPhotoSelectForOne();
}
}
//For Android 5.0+ 多个文件选择
public boolean onShowFileChooser(
WebView webView, ValueCallback<Uri[]> filePathCallback,
WebChromeClient.FileChooserParams fileChooserParams){
mUMA = filePathCallback;
if(onFileSelected!=null){
onFileSelected.onSelect(mUM,mUMA);
}
if(webFileFactory!=null){
webFileFactory.setmUMA(mUMA);
webFileFactory.showPhotoSelect();
}
return true;
}
}
/**
* 设置webview安全性
*/
private void setWebViewSecurity(){
try {
removeJavascriptInterface("searchBoxJavaBridge_");
removeJavascriptInterface("accessibility");
removeJavascriptInterface("accessibilityTraversal");
getSettings().setSavePassword(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
} catch (Exception e) {
}
}
public interface OnFileSelected{
void onSelectOne(ValueCallback<Uri> mUM, ValueCallback<Uri[]> mUMA);
void onSelect(ValueCallback<Uri> mUM, ValueCallback<Uri[]> mUMA);
}
}
支持视频播放
webView.setSupportVideo(webView.new CommonWebChromeClient());
支持文件上传
webView.setSupportFile(wbw_web.new CommonWebChromeClient());
网友评论