Android爬坑之行之WebView

原题目:Android爬坑之行之WebView 不知道不觉,Hybird App早已变成现阶段较为流行的一种开发设计方法。 针对客户感受规定较高或是与硬件配置互动较多的作用大家一般都是选用Native原生

原题目:Android爬坑之行之WebView

不知道不觉,Hybird App早已变成现阶段较为流行的一种开发设计方法。

针对客户感受规定较高或是与硬件配置互动较多的作用大家一般都是选用Native原生态的方法来完成。

而客户互动少,偏展现类,主题活动类的作用大家则一般选用H5的方法来完成,

比如新闻报道类的app,详细信息展现页一般便是H5的网页页面

一层面文图排版设计上web拥有先天性的优点,同时纯展现类的网页页面在现阶段的移动终端上,特性感受早已难以让客户辨别是网页页面還是原生态了; 另外一层面,H5的网页页面混合开发,便捷在原生态顾客端上完成共享作用,有着极强的散播性,大家平常普遍的主题活动网页页面也有着那样的优点,因此你看看到的主题活动网页页面也基本全是H5,只需轻轻地一点就可以共享到每个服务平台; 同时,H5的网页页面开发设计减少了开发设计成本费,一套编码,web,android,ios都能浏览。
南宫市企业网站建设(但是具体开发设计全过程中,H5的兼容也全是各种各样泪)

即然Hybird App有那么多优点,那在Android中大家根据哪些的方法在原生态新项目中置入H5网页页面呢?

那么就不可不提及大家的WebVew了,做为官方网唯一用于显示信息web的部件,

展现网页页面那样的每日任务也只有交到它了。

A View that displays web pages. This class is the basis upon which you can roll your own web browser or simply display some online content within your Activity. It uses the WebKit rendering engine to display web pages and includes methods to navigate forward and backward through a history, zoom in and out, perform text searches and more.

引入官方网文本文档的一句话:

WebView是一个用于在Activity中显示信息大家网页页面的主视图部件,它根据webkit3D渲染模块3D渲染和显示信息大家的web网页页面,而且包括了web的历史时间导航栏操法,网页页面变大变小,文字检索等方式。

大家最先看来一下WebView的基本使用方法:

WebView的基本使用方法

有关WebView的基本使用方法,大部分分人也是驾轻就熟,

原本也是写了一一部分,不经意中发觉有一位时尚博主的blog对WebView的详细介绍确实太过详尽,像我那样的懒人,有更强的文章内容不是会自身去写的,

因此删了自身写的,将大神时尚博主的blog共享出去,很感兴趣同学们的能够一起看一看:

Android WebView 开发设计详细说明(一)

Android WebView 开发设计详细说明(二)

Android WebView 开发设计详细说明(三)

掌握完WebView的基本使用方法,那么就来小结下近期新项目中碰到的有关WebView的坑

新项目中应用WebView碰到的难题WebView页面的原生态题目设定

Picture

如图所示所显示,

一般状况下,大家WebView所属页面由顶端带题目的原生态导航栏栏跟WebView的內容一部分构成,

而WebView中的页面将会在点一下后还会继续再跳别的Web网页页面(如图所示点一下休假会在当今WebView自动跳转休假的Web网页页面)。

因为点一下內容的不确定性性,因此一般状况下,非常简单的作法便是捕捉h5网页页面的 title 标识来开展题目设定。

针对捕捉 title 标识內容的方法,WebView也非常好地出示了适用,大家能够根据承继WebChromeClient的onReceivedTitle来开展获得:

privateclassWebViewChromeClientextendsWebChromeClient{

@Override

publicvoidonReceivedTitle(WebView view, String title){

super.onReceivedTitle(view, title);

mTitleText.setTitle(String.valueOf(view.getTitle()));

}

}

但是那样的方法在具体应用中有一个难题:

当根据 webView.goBack() 方法回到上一级Web网页页面的情况下不容易开启这一方式,因而会造成题目没法追随历史时间纪录回到上一级网页页面。

因此在新项目中,大家能够根据重新写过 WebViewClient 的 onPageFinished 方式,在 onPageFinished 中对页面题目开展设定。

由于无论是历史时间纪录的回到還是点一下自动跳转都是开启网页页面载入,当网页页面载入进行时(不包含js动态性建立及其img照片载入结束)都是开启onPageFinished 这一方式,

这时大家去获得 title 的题目內容不容易有一切难题,能够保证在网页页面回到时可以获得到恰当的题目。

mWebView.setWebViewClient( newWebViewClient(){

//Web网页页面每一次载入并进行时候开启该方式

@Override

publicvoidonPageFinished(WebView view, String url){

super.onPageFinished(view, url);

mToolbar.setTitle(String.valueOf(view.getTitle()));

Log.i (LOG_TAG, "onPageFinished");

}

});

注: 这类作法有一个缺点,便是回到上一个页面的情况下,等网页页面载入进行的情况下题目才会显示信息出去,以便更强地提升,大家能够建立一个结合用于储存大家的题目,载入url的情况下把题目加上进结合,当回到上一级网页页面的情况下,从结合中取下题目开展显示信息,同时从结合中清除题目。

WebView中的Web网页页面存有 input type='file' 标识时没法开启文档挑选器

在大家的手机上访问器中,当web网页页面中有 input type='file' 按键标识的情况下点一下会全自动开启系统软件的文档挑选器,但是这一作用在流行系统软件的WebView中沒有被默认设置完成,

因而,以便让 input type='file' 点一下时可以开启系统软件的文档挑选器,大家务必根据重新写过 WebChromeClient 来完成点一下 input type='file' 开启系统软件文档挑选器。

编码以下:

publicclassMainActivityextendsAppCompatActivity{

/** Android 5.0下列版本号的文档挑选回调函数 */

protectedValueCallback Uri mFileUploadCallbackFirst;

/** Android 5.0及之上版本号的文档挑选回调函数 */

protectedValueCallback Uri[] mFileUploadCallbackSecond;

protectedstaticfinalintREQUEST_CODE_FILE_PICKER = 51426;

protectedString mUploadableFileTypes = "image/*";

privateWebView mWebView;

@Override

protectedvoidonCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

initWebView();

}

privatevoidinitWebView(){

mWebView = (WebView) findViewById(R.id.my_webview);

mWebView.loadUrl( "file:///android_asset/index.html");

mWebView.setWebChromeClient( newOpenFileChromeClient());

}

privateclassOpenFileChromeClientextendsWebChromeClient{

// Android 2.2 (API level 8)到Android 2.3 (API level 10)版本号挑选文档时候开启该掩藏方式

@SuppressWarnings( "unused")

publicvoidopenFileChooser(ValueCallback Uri uploadMsg){

openFileChooser(uploadMsg, null);

}

// Android 3.0 (API level 11)到 Android 4.0 (API level 15))版本号挑选文档时候开启,该方式为掩藏方式

publicvoidopenFileChooser(ValueCallback Uri uploadMsg, String acceptType){

openFileChooser(uploadMsg, acceptType, null);

}

// Android 4.1 (API level 16) -- Android 4.3 (API level 18)版本号挑选文档时候开启,该方式为掩藏方式

@SuppressWarnings( "unused")

publicvoidopenFileChooser(ValueCallback Uri uploadMsg, String acceptType, String capture){

openFileInput(uploadMsg, null, false);

}

// Android 5.0 (API level 21)之上版本号会开启该方式,该方式为公布方式

@SuppressWarnings( "all")

publicbooleanonShowFileChooser(WebView webView, ValueCallback Uri[] filePathCallback, WebChromeClient.FileChooserParams fileChooserParams){

if(Build.VERSION.SDK_INT = 21) {

finalbooleanallowMultiple = fileChooserParams.getMode() == FileChooserParams.MODE_OPEN_MULTIPLE; //是不是适用选取

openFileInput( null, filePathCallback, allowMultiple);

returntrue;

}

else{

returnfalse;

}

}

}

@SuppressLint( "NewApi")

protectedvoidopenFileInput(finalValueCallback Uri fileUploadCallbackFirst, finalValueCallback Uri[] fileUploadCallbackSecond, finalbooleanallowMultiple){

//Android 5.0下列版本号

if(mFileUploadCallbackFirst != null) {

mFileUploadCallbackFirst.onReceiveValue( null);

}

mFileUploadCallbackFirst = fileUploadCallbackFirst;

//Android 5.0及之上版本号

if(mFileUploadCallbackSecond != null) {

mFileUploadCallbackSecond.onReceiveValue( null);

}

mFileUploadCallbackSecond = fileUploadCallbackSecond;

Intent i = newIntent(Intent.ACTION_GET_CONTENT);

i.addCategory(Intent.CATEGORY_OPENABLE);

if(allowMultiple) {

if(Build.VERSION.SDK_INT = 18) {

i.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);

}

}

i.setType(mUploadableFileTypes);

startActivityForResult(Intent.createChooser(i, "挑选文档"), REQUEST_CODE_FILE_PICKER);

}

publicvoidonActivityResult(finalintrequestCode, finalintresultCode, finalIntent intent){

if(requestCode == REQUEST_CODE_FILE_PICKER) {

if(resultCode == Activity.RESULT_OK) {

if(intent != null) {

//Android 5.0下列版本号

if(mFileUploadCallbackFirst != null) {

mFileUploadCallbackFirst.onReceiveValue(intent.getData());

mFileUploadCallbackFirst = null;

}

elseif(mFileUploadCallbackSecond != null) { //Android 5.0及之上版本号

Uri[] dataUris = null;

try{

if(intent.getDataString() != null) {

dataUris = newUri[] { Uri.parse(intent.getDataString()) };

}

else{

if(Build.VERSION.SDK_INT = 16) {

if(intent.getClipData() != null) {

finalintnumSelectedFiles = intent.getClipData().getItemCount();

dataUris = newUri[numSelectedFiles];

for( inti = 0; i numSelectedFiles; i++) {

dataUris[i] = intent.getClipData().getItemAt(i).getUri();

}

}

}

}

}

catch(Exception ignored) { }

mFileUploadCallbackSecond.onReceiveValue(dataUris);

mFileUploadCallbackSecond = null;

}

}

}

else{

//这儿mFileUploadCallbackFirst跟mFileUploadCallbackSecond不在同系统软件版本号下各自拥有了

//WebView目标,再用户撤销文档挑选器的状况下,需给onReceiveValue传null回到值

//不然WebView在未接到回到值的状况下,没法开展一切实际操作,文档挑选器会无效

if(mFileUploadCallbackFirst != null) {

mFileUploadCallbackFirst.onReceiveValue( null);

mFileUploadCallbackFirst = null;

}

elseif(mFileUploadCallbackSecond != null) {

mFileUploadCallbackSecond.onReceiveValue( null);

mFileUploadCallbackSecond = null;

}

}

}

}

}

注:当客户点一下input file弹出来文档挑选器后,点一下撤销或是回到按键沒有实行挑选时,务必在onActivityResult里给valueCallback的onReceiveValue传null,由于valueCallback拥有的是WebView,在onReceiveValue沒有回传值的状况下,WebView没法开展下一步实际操作,会造成撤销挑选文档后,点一下input file不容易再响应:

if(mFileUploadCallbackFirst != null) {

mFileUploadCallbackFirst.onReceiveValue( null);

mFileUploadCallbackFirst = null;

}

elseif(mFileUploadCallbackSecond != null) {

mFileUploadCallbackSecond.onReceiveValue( null);

mFileUploadCallbackSecond = null;

}

实例demo详细地址:

https://github/cjpx00008/FileChooser4WebViewDemo

WebView中的web网页页面启用系统软件挑选器或是照相机造成app进到后台管理被系统软件释放出来

大家都知道,WebView根据webkit核心来3D渲染web网页页面,因而应用起來非常于一个中小型访问器,即便网页页面內容不负杂,要是应用WebView也会占有很多的运行内存。

而Android的运行内存收购体制,在系统软件运行内存不够的状况下能优先选择释放出来运行内存占有很大的app进而收购运行内存資源,这时已经应用WebView的运作在后台管理的app毫无疑问是当仁不让被收购的。

因而,当WebView根据input file启用系统软件文档挑选器,或是根据文档挑选器启用了照相机时,大家的app就进到了后台管理,在一部分中低端Android机器设备(特别是在红米这种手机上,默认设置的神隐方式会在app进到后台管理的情况下很大几率的释放出来app)或是系统软件运行内存資源不够的状况下,大家的app便会优先选择被释放出来掉,造成文档挑选结束后,返回上一页面时,app的页面再次离开了onCreate,web网页页面也因而复建了。

针对一部分必须填好很多表格的web网页页面来讲,客户填好的数据信息会伴随着页面的消毁复建而遗失,而挑选的文档也由于网页页面的复建而没法回发送给input file,这针对客户的感受来讲毫无疑问不是友善的。

或许你能说,重新写过onSaveInstance储存数据信息便是啦。

这也就是我一刚开始考虑到的,

大家的WebView也出示了 saveState 及其 restoreState 来储存情况。

但是悲惨的是,这2个方式其实不会储存web网页页面内的数据信息,它只储存了WebView载入的网页页面,前行倒退的历史时间情况等数据信息。

引入官方网文本文档的叙述:

Saves the state of this WebView used in onSaveInstanceState(Bundle)

. Please note that this method no longer stores the display data for this WebView. The previous behavior could potentially leak files if restoreState(Bundle)

was never called.

Please note that this method no longer stores the display data for this WebView

WebView的saveState其实不会储存页面的数据信息。

因此,针对表格数据信息的修复,大家只有自身想方法了,大家这儿选用了两个计划方案:

根据WebView与JS互动,在onSaveInstance的情况下开启页面储存数据信息,储存数据信息的方法也大致分成二种, 一种应用H5内置的localStorage来开展数据信息储存,网页页面消毁复建的情况下H5网页页面分辨当地localStorage数据信息是不是有值,有就将值再次添充到网页页面表格,递交数据信息后消除当地localStorage的数据信息。 这类方法必须给WebView打开对localStorage的适用。 WebSettings settings = mWebView.getSettings();

settings.setDomStorageEnabled( true);

另外一种则出示JS插口将数据信息传送给原生态,根据原生态编码将数据信息储存到当地,在网页页面复建3D渲染进行时,web网页页面根据JS插口启用原生态方式拉取数据信息分辨是不是有值,有则添充表格,无则不做实际操作,递交数据信息后启用JS插口启用原生态方式清除当地数据信息。

由web端自身解决,在表格网页页面文字键入丧失聚焦点时全自动储存数据信息,网页页面消毁复建时,自身拉取数据信息开展分辨。 这类方法对原生态的依靠较低,本人更趋向这类方法,自然最后因为新项目的独特状况,大家還是选用了第一种方法。

之上是表格数据信息的修复计划方案,

而针对从系统软件文档挑选器挑选的文档web网页页面是没法立即接受并解决了,这儿大家出示了一个JS插口在web网页页面载入进行时,开展开启,并将数据信息传送给web网页页面。

说到这儿,不可不提此外一个难题

WebView启用服务端网页页面怎样浏览当地文档

上边大家提及了根据JS插口将挑选的文档数据信息传送给web网页页面,

但是因为安全性缘故,WebView限定了远程控制url网页页面浏览当地文档,

假如大家载入的url是服务端的网页页面,那么我们沒有一切方法立即根据文档详细地址到访问顾客端当地的文档

大家了解,WebView用于载入网页页面的方法关键有三种:

loadUrl( Stringurl)

loadUrl( Stringurl, Map String, String additionalHttpHeaders)

loadData( Stringdata, StringmimeType, Stringencoding)

loadDataWithBaseURL( StringbaseUrl, Stringdata, StringmimeType, Stringencoding, StringhistoryUrl)

loadData()和loadDataWithBaseURL()全是立即将数据信息载入进WebView中,非常于显示信息的一个当地Web

loadUrl还可以根据浏览当地的文档详细地址(比如当地asset文件目录下的储放了index.html网页页面,能够根据loadUrl("file:///android_asset/index.html")来显示信息web网页页面)

针对那样的三种载入当地內容的方法,大家可使用多种多样方法来传送相对路径供web网页页面传送,这儿以照片为例子(相册图片文件目录下test/IMG_20170105_093405.jpg):

立即根据文档的肯定详细地址来出示给网页页面显示信息: imgsrc= 'file:///storage/emulated/0/dcim/test/IMG_20170105_093405.jpg'/ 根据新闻媒体库查寻出去的content uri详细地址展现 imgsrc= 'content://media/external/images/media/102610'/ 根据FileProvider变换的content uri详细地址展现 imgsrc= 'content://com.test.myfileprovider/dcim/test/IMG_20170105_093405.jpg'/

可如果你应用loadUrl(String url)载入服务端的http详细地址时,之上三种方式将均没法应用,历经各种各样试着,现阶段寻找二种计划方案来出示给web端开展照片显示信息:

由原生态编码解决,将文档运转换为Base64以后根据JS插口回发送给web; 重新写过WebViewClient里的shouldInterceptRequest方式,每每网页页面产生資源恳求的情况下便会开启这一方式,大家能够过虑恳求,分辨恳求是不是为当地文档,根据阻拦恳求变换为二进制流回传到去, 实例编码以下: mWebView.setWebViewClient( newWebViewClient(){

@Override

publicWebResourceResponse shouldInterceptRequest(WebView view, String url){

if(url.startsWith( "http://") url.endWith( ".jpg") {

returngetWebResourceResponse( "/storage/emulated/0/dcim/trinaic/IMG_20170105_093405.jpg", "image/jpeg", ".jpg");

}

returnsuper.shouldInterceptRequest(view, url);

}

}

privateWebResourceResponse getWebResourceResponse(String url, String mime, String style){

WebResourceResponse response = null;

try{

response = newWebResourceResponse(mime, "UTF-8", newFileInputStream( newFile(url)));

} catch(FileNotFoundException e) {

e.printStackTrace();

}

returnresponse;

}

WebView JS引入系统漏洞

要想让原生态跟JS开展互动,依照官方网出示的方式就得应用addJavaInterface

classJsObject{

@JavaInterface

publicString toString(){ return"injectedObject"; }

}

webView.addJavaInterface( newJsObject(), "injectedObject");

webView.loadData( "", "text/html", null);

webView.loadUrl( "java:alert(injectedObject.toString())");

Injects the supplied Java object into this WebView. The object is injected into the Java context of the main frame, using the supplied name. This allows the Java object's methods to be accessed from Java. For applications targeted to API level JELLY_BEAN_MR1

and above, only public methods that are annotated with JavaInterface

can be accessed from Java. For applications targeted to API level JELLY_BEAN

or below, all public methods (including the inherited ones) can be accessed, see the important security note below for implications.

引入官方网api的表明,在Android 4.2下列,会出现被引入的风险性,4.。

实际的引入方法,我找了篇blog,假如有不清晰的同学们就行了解下:

Android WebView的Js目标引入系统漏洞处理计划方案

在以前黑云服务平台给出的系统漏洞中,

android/webkit/webview中默认设置内嵌的一个searchBoxJavaBridge_ 插口同时存有远程控制编码实行系统漏洞

取决于android/webkit/AccessibilityInjector.java中,启用了此部件的运用在打开輔助作用选择项中第三方服务的安卓系统系统软件时会导致远程控制编码实行系统漏洞。这2个插口各自是"accessibility" 和"accessibilityTraversal" ,此系统漏洞基本原理与searchBoxJavaBridge_插口远程控制编码实行类似,均为未清除躁动不安全的默认设置插口,但是此系统漏洞必须客户起动系统软件设定中的第三方輔助服务,运用标准较繁杂。

因而,一般状况下大家根据removeJavaeInterface来清除这好多个插口

if(Build.VERSION.SDK_INT 17) {

mAdvanceWebView.removeJavaInterface( "searchBoxJavaBridge_");

mAdvanceWebView.removeJavaInterface( "accessibility");

mAdvanceWebView.removeJavaInterface( "accessibilityTraversal");

}

此外也是有根据onJsPrompt的方法来完成WebView原生态跟JS互动作用的,github上的开源系统新项目JSBridge便是选用这类方式:

https://github/lzyzsd/JsBridge

以前拜读过名字鼎鼎的cordova的源代码,它內部的原生态JS互动也是选用onJsPrompt的方法,但是在这个基础上干了更强劲的封裝。

WebView后台管理耗电难题

当我们们的WebView的web网页页面在分析或是播发视頻再或是有js定时执行器在实行的时,

假如大家把运用退到后台管理,不做一切解决的状况下,之上的实际操作还会继续在后台管理再次实行,造成WebView在后台管理不断耗电,因而一般大家会做下列解决

@Override

protectedvoidonPause(){

super.onPause();

mWebView.onPause(); //中止一部分可安全性解决的实际操作,如动漫,精准定位,视頻播发等

mWebView.pauseTimers(); //中止全部WebView的网页页面合理布局、分析及其Java的定时执行器实际操作

}

@Override

protectedvoidonResume(){

super.onResume();

mWebView.onResume();

mWebView.resumeTimers();

}

针对WebView的应用,在解决难题的全过程中发觉一个非常好的开源系统库:

https://github/delight-im/Android-AdvancedWebView

大部分上边我提及的或是没提及的难题它都干了一定的封裝解决,而且考虑到了一些版本号兼容的难题,能够立即用来应用,还可以用来参照学习培训。

假如你感觉难题還是过多得话还可以考虑到应用腾迅访问服务,根据QQ访问器X5核心,兼容了Android所有流行服务平台,能够在全部Android手机上上应用Blink的技术性工作能力,具备更强的H5/CSS3适用和特性,现阶段手机微信、qq都会应用它。

唯一的缺点便是它不出示装包核心版的SDK,第一次应用时,它会全自动到腾迅服务端去免费下载核心,免费下载结束之后弹出窗口提醒客户是不是重新启动app,重新启动以后就可以一切正常应用x5访问服务了,假如你没在意那样的客户感受,能够考虑到立即应用腾迅访问服务。

(填补)

WebView搞混难题

假如app装包搞混以后发觉出示给web网页页面的JS插口无效了,还记得查验是不是加上了JavaInterface的搞混配备:

-keepclassmembers class* {

@android.webkit.JavaInterface methods

}

红米WebView內部Web网页页面的div本身翻转条难题

红米上WebView內部的Web网页页面的div因为內容高宽比超过div,造成了根据div的翻转条(WebView翻转条已禁止使用的状况下),根据设定div的css款式来禁止使用div翻转条

Htmldom原素 ID或 class:: -webkit-scrollbar{ display:none}

WebView內部web网页页面px跟dp的关联

经检测发觉,WebView內部web网页页面的px值会以内部全自动变换为dp,且1px=1dp,跟ppi值不相干,这一点跟原生态开发设计中的1dp = 机器设备ppi/160 * px计算关联nveou

大伙儿都会看回到凡科,查询大量

义务编写:

  • 14张动图,深层剖析H5网页

    我国的H5网页页面网页页面制作专用型专用工具,一般指HTML5网页页面网页页面的网上撰写器——注意,是网上的,因而大多数数是一个包括万象的网站。国外则多见线下推广手机上手机

  • 零基本学习培训web前端开

    模拟题目:零基本学习培训学习培训web前端开发开发设计开发设计设计方案学习培训学习培训路线 移动互联网网网的快速发展趋势发展趋势让web前端开发开发设计开发设计设计方案工作

  • 网易游戏“社会学气场”

    社交媒体贷币定义源于《疯传:给你的商品、观念、个人行为像病毒感染一样侵入》,通俗化的说便是在社交媒体关联链中来源于别人的关心、认可。 大家乐在其中地耗费专业知识贮备

  • 响应式自助建站模板下载

    H5响应式自助式式建设网站模板完全免费免费下载,如何搭建网站?这也是很多企业朋友关注的话题,完全免费免费下载模板后如何搭建本身的响应式网站。确实,响应式自助式式建设网

  • 这一情况难题,疑惑了好

    模拟题目:这一状况难点,疑虑了很久...... 文图排版设计设计方案 H5场景秀 H5文图秀 手机上前文图 今天来讲一个场景秀建议意见反馈表格中吐槽得最多的一个难点:为何场景秀的状况