protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView webview = (WebView) findViewById(R.id.web_view);
assert webview != null;
WebSettings settings = webview.getSettings();
settings.setUseWideViewPort(true);
settings.setLoadWithOverviewMode(true);
settings.setJavaScriptEnabled(true);
webview.setWebChromeClient(new WebChromeClient() {
// android 3.0以下:用的这个方法
public void openFileChooser(ValueCallback valueCallback) {
uploadMessage = valueCallback;
openImageChooserActivity();
}
// android 3.0以上,android4.0以下:用的这个方法
public void openFileChooser(ValueCallback valueCallback, String acceptType) {
uploadMessage = valueCallback;
openImageChooserActivity();
}
//android 4.0 - android 4.3 安卓4.4.4也用的这个方法
public void openFileChooser(ValueCallback valueCallback, String acceptType,
String capture) {
uploadMessage = valueCallback;
openImageChooserActivity();
}
//android4.4 无方法。。。
// Android 5.0及以上用的这个方法
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]>
filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
uploadMessageAboveL = filePathCallback;
openImageChooserActivity();
return true;
}
});
String targetUrl = “file:///android_asset/up.html”;
webview.loadUrl(targetUrl);
}
private void openImageChooserActivity() {
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType(“image/*”);
startActivityForResult(Intent.createChooser(i, “Image Chooser”),
FILE_CHOOSER_RESULT_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == FILE_CHOOSER_RESULT_CODE) {
if (null == uploadMessage && null == uploadMessageAboveL) return;
Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
if (uploadMessageAboveL != null) {
onActivityResultAboveL(requestCode, resultCode, data);
} else if (uploadMessage != null) {
uploadMessage.onReceiveValue(result);
uploadMessage = null;
}
}
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void onActivityResultAboveL(int requestCode, int resultCode, Intent intent) {
if (requestCode != FILE_CHOOSER_RESULT_CODE || uploadMessageAboveL == null)
return;
Uri[] results = null;
if (resultCode == Activity.RESULT_OK) {
if (intent != null) {
String dataString = intent.getDataString();
ClipData clipData = intent.getClipData();
if (clipData != null) {
results = new Uri[clipData.getItemCount()];
for (int i = 0; i < clipData.getItemCount(); i++) {
ClipData.Item item = clipData.getItemAt(i);
results[i] = item.getUri();
}
}
if (dataString != null)
results = new Uri[]{Uri.parse(dataString)};
}
}
uploadMessageAboveL.onReceiveValue(results);
uploadMessageAboveL = null;
}
重点坑:针对Android4.4,系统把openFileChooser方法去掉了,怎么解决?
详情请见博客
http://blog.csdn.net/xiexie758/article/details/52446937这里就不多说了。
(6) WebView调用手机系统相册来上传图片,处理好第六点说的方法,我们打好release包测试的时候却又发现还是没法选择图片了,怎么解决?
原因分析:
无奈去翻WebChromeClient的源码,发现openFileChooser()是系统API,我们的release包是开启了混淆的,所以在打包的时候混淆了openFileChooser(),这就导致无法回调openFileChooser()了。
解决方案
也很简单,直接不混淆openFileChooser()就好了。
-keepclassmembers class * extends android.webkit.WebChromeClient{
public void openFileChooser(…);
}
(7)怎么在 WebView 中长按保存图片?
1.给 WebView添加监听
mWebview.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
}
});
2.获取点击的图片地址
先获取类型,根据相应的类型来处理对应的数据。
//首先判断点击的类型
WebView.HitTestResult result = ((WebView) v).getHitTestResult();
int type = result.getType();
//获取具体信息,图片这里就是图片地址
String imgurl = result.getExtra();
type有这几种类型:
-
WebView.HitTestResult.UNKNOWN_TYPE 未知类型
-
WebView.HitTestResult.PHONE_TYPE 电话类型
-
WebView.HitTestResult.EMAIL_TYPE 电子邮件类型
-
WebView.HitTestResult.GEO_TYPE 地图类型
-
WebView.HitTestResult.SRC_ANCHOR_TYPE 超链接类型
-
WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE 带有链接的图片类型
-
WebView.HitTestResult.IMAGE_TYPE 单纯的图片类型
-
WebView.HitTestResult.EDIT_TEXT_TYPE 选中的文字类型
3.操作图片
你可以弹出保存图片,或者点击之后跳转到显示图片的页面。
最后整理一下代码:
mWebView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
WebView.HitTestResult result = ((WebView)v).getHitTestResult();
if (null == result)
return false;
int type = result.getType();
if (type == WebView.HitTestResult.UNKNOWN_TYPE)
return false;
// 这里可以拦截很多类型,我们只处理图片类型就可以了
switch (type) {
case WebView.HitTestResult.PHONE_TYPE: // 处理拨号
break;
case WebView.HitTestResult.EMAIL_TYPE: // 处理Email
break;
case WebView.HitTestResult.GEO_TYPE: // 地图类型
break;
case WebView.HitTestResult.SRC_ANCHOR_TYPE: // 超链接
break;
case WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE:
break;
case WebView.HitTestResult.IMAGE_TYPE: // 处理长按图片的菜单项
// 获取图片的路径
String saveImgUrl = result.getExtra();
// 跳转到图片详情页,显示图片
Intent i = new Intent(MainActivity.this, ImageActivity.class);
i.putExtra(“imgUrl”, saveImgUrl);
startActivity(i);
break;
default:
break;
}
}
});
(8) WebView 开启硬件加速导致的问题?
WebView有很多问题,比如:不能打开pdf,播放视屏也只能打开硬件加速才能支持,在某些机型上会崩溃。
下面看一下硬件加速, 硬件加速分为四个级别:
Application级别
<application android:hardwareAccelerated=“true”…>
Activity级别
<activity android:hardwareAccelerated=“true”…>
window级别(目前为止,Android还不支持在Window级别关闭硬件加速。)
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
View级别
view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
WebView开启硬件加速导致屏幕花屏问题的解决:
原因分析:
4.0以上的系统我们开启硬件加速后,WebView渲染页面更加快速,拖动也更加顺滑。但有个副作用就是,当WebView视图被整体遮住一块,然后突然恢复时(比如使用SlideMenu将WebView从侧边滑出来时),这个过渡期会出现白块同时界面闪烁。
解决方案:
在过渡期前将WebView的硬件加速临时关闭,过渡期后再开启,代码如下:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
Android 4.0+ 版本中的EditText字符重叠问题:
做的软件,在一些机器上,打字的时候,EditText中的内容会出现重叠,而大部分机器没有,所以感觉不是代码的问题,一直没有头绪。
出现原因:JellyBean的硬件加速bug,在此我们关掉硬件加速即可。
解决方案:在EditText中加入一句:
android:layerType=”software”
图片无法显示:
做的程序里有的时候会需要加载大图,但是硬件加速中 OpenGL对于内存是有限制的。如果遇到了这个限制,LogCat只会报一个Warning: Bitmap too large to be uploaded into a texture (587x7696, max=2048x2048)
这时我们就需要把硬件加速关闭了。
但开始我是这样处理的,我关闭了整个应用的硬件加速:
<application
android:allowBackup=“true”
android:icon=“@drawable/ic_launcher”
android:hardwareAccelerated=“false”
android:label=“@string/app_name”
android:theme=“@style/AppTheme” >
随后我就发现,虽然图片可以显示了,但是ListView和WebView等控件显得特别的卡,这说明硬件加速对于程序的性能提升是很明显的。所以我就改为对于Activity的关闭。
<activity
android:name=“icyfox.webviewimagezoomertest.MainActivity”
android:label=“@string/app_name”
android:hardwareAccelerated=“false”
(9) ViewPager里非首屏WebView点击事件不响应是什么原因?
如果你的多个WebView是放在ViewPager里一个个加载出来的,那么就会遇到这样的问题。ViewPager首屏WebView的创建是在前台,点击时没有问题;而其他非首屏的WebView是在后台创建,滑动到它后点击页面会出现如下错误日志:
20955-20968/xx.xxx.xxx E/webcoreglue﹕ Should not happen: no rect-based-test nodes found
解决方案:
这个问题的办法是继承WebView类,在子类覆盖onTouchEvent方法,填入如下代码:
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onScrollChanged(getScrollX(), getScrollY(), getScrollX(), getScrollY());
}
return super.onTouchEvent(ev);
}
WebView新增了一些非常有用的API,可以使用和chrome浏览器类似的API来实现对恶意网站的检测来保护web浏览的安全性,为此需要在manifest中添加如下meta-data标签:
<meta-data
android:name=“android.webkit.WebView.EnableSafeBrowing”
android:value=“true” />
WebView还增加了关于多进程的API,可以使用多进程来增强安全性和健壮性,如果render进程崩溃了,你还可以使用Termination Handler API来检测到崩溃并做出相应处理。
(1)给WebView加一个加载进度条
用Webview加载一个网页时,如果加载时间长,界面会一直空白,体验不太好,所以加个进度条更好看一下,主流APP也都有进度条效果,大概思路我来说一下:
首先自定义一个HorizontalProgressView继承View,然后自定义一个MyWebView继承WebView,然后初始化的时候通过addView方法把前面自定义HorizontalProgressView,然后在MyWebView里面写一个内部类继承WebChromeClient,大致代码如下:
private class MyWebCromeClient extends WebChromeClient {
@Override
public void onProgressChanged(WebView view, int newProgress) {
if (newProgress == 100) {
//加载完毕进度条消失
progressView.setVisibility(View.GONE);
} else {
//更新进度
progressView.setProgress(newProgress);
}
super.onProgressChanged(view, newProgress);
}
}
主要是通过MyWebCromeClient 的onProgressChanged方法里面的进度值调用
progressView.setProgress()方法去更新进度条,当加载100%的时候让进度条消失。
具体实现你们自己去处理吧。
(2)加快HTML网页加载完成的速度,等页面finish再加载图片
默认情况html代码下载到WebView后,webkit开始解析网页各个节点,发现有外部样式文件或者外部脚本文件时,会异步发起网络请求下载文件,但如果在这之前也有解析到image节点,那势必也会发起网络请求下载相应的图片。
在网络情况较差的情况下,过多的网络请求就会造成带宽紧张,影响到css或js文件加载完成的时间,造成页面空白loading过久。解决的方法就是告诉WebView先不要自动加载图片,等页面finish后再发起图片加载。
解决办法:
在WebView初始化时设置如下代码:
public void int () {
if(Build.VERSION.SDK_INT >= 19) {
webView.getSettings().setLoadsImagesAutomatically(true);
} else {
webView.getSettings().setLoadsImagesAutomatically(false);
}
}
同时在WebView的WebViewClient实例中的onPageFinished()方法添加如下代码:
@Override
public void onPageFinished(WebView view, String url) {
if(!webView.getSettings().getLoadsImagesAutomatically()) {
webView.getSettings().setLoadsImagesAutomatically(true);
}
}
(3)自定义WebView页面加载出错界面
当WebView加载页面出错时(一般为404 NOT FOUND),安卓WebView会默认显示一个卖萌的出错界面。但我们怎么能让用户发现原来我使用的是网页应用呢,我们期望的是用户在网页上得到是如原生般应用的体验,那就先要从干掉这个默认出错页面开始。
当WebView加载出错时,我们会在WebViewClient实例中的onReceivedError()方法接收到错误,我们就在这里做些手脚:
@Override
public void onReceivedError (WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
loadDataWithBaseURL(null, “”, “text/html”, “utf-8”, null);
mErrorFrame.setVisibility(View.VISIBLE);
}
从上面可以看出,我们先使用loadDataWithBaseURL清除掉默认错误页内容,再让我们自定义的View得到显示(mErrorFrame为蒙在WebView之上的一个LinearLayout布局,默认为View.GONE)。
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
", null);
mErrorFrame.setVisibility(View.VISIBLE);
}
从上面可以看出,我们先使用loadDataWithBaseURL清除掉默认错误页内容,再让我们自定义的View得到显示(mErrorFrame为蒙在WebView之上的一个LinearLayout布局,默认为View.GONE)。
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-8dDxR1Bl-1715710707297)]
[外链图片转存中…(img-9S9jwOhY-1715710707297)]
[外链图片转存中…(img-aih28pg9-1715710707298)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!