放弃WebView使用Crosswalk做富文本编辑器.docx
- 文档编号:25237219
- 上传时间:2023-06-06
- 格式:DOCX
- 页数:16
- 大小:21.30KB
放弃WebView使用Crosswalk做富文本编辑器.docx
《放弃WebView使用Crosswalk做富文本编辑器.docx》由会员分享,可在线阅读,更多相关《放弃WebView使用Crosswalk做富文本编辑器.docx(16页珍藏版)》请在冰豆网上搜索。
放弃WebView使用Crosswalk做富文本编辑器
放弃WebView,使用Crosswalk做富文本编辑器
版权声明:
欢迎转载,但请保留文章原始出处作者:
GavinCT出处:
为什么放弃WebView
AndroidWebView做普通浏览还好,做富文本编辑器(执行js:
document.body.contentEditable=true;),常常会遇到各种奇葩的bug,而且很难修复。
尽管Google在版本迭代中不断修复bug,但依旧没法用它来做富文本编辑。
Kitkat的改变
Google为了加强WebView的功能,在Kitkat引入了Chromium内核。
但还是存在着编辑的bug。
我所知道的一个bug是:
Kitkat版WebView在删除Html标签时处理不好,例如标签,就无法删除。
点击删除时直接越过此元素,将光标定位在图片前方,对图片不做处理。
当然,这个bug在Android5.0修复了。
Lollipop新策略
AlthoughWebViewhasbeenbasedonChromiumsinceAndroid4.4,theChromiumlayerisnowupdatablefromGooglePlay.
AsnewversionsofChromiumbecomeavailable,userscanupdatefromGooglePlaytoensuretheygetthelatestenhancementsandbugfixesforWebView,providingthelatestwebAPIsandbugfixesforappsusingWebViewonAndroid5.0andhigher.
可见在Lollipop里,可以通过GooglePlay来更新Chromium内核。
但是问题来了:
国内容易更新么?
如果不是自动更新,用户会手动更新么?
当然GooglePlay是自动更新,那国内手机没有自己市场的厂商呢?
Lollipop以前的版本怎么办?
Lollipop目前只有很少用户可以更新。
探索新的富文本编辑方案
显然,即便是有了Lollipop的解决方案,但问题依然很多。
我们还是需要一个替代方案,来保证我们在所有的Android手机上表现一致。
这个方案就是在应用中集成Chromium。
由于自己编译Chromium的难度较大,于是转而寻找编译好的Chromium库来使用。
需要声明的是:
Chromium内核只能在Android4.0以上才能使用,之后提到的所有Chromium库都只能在4.0以上平台使用。
过渡方案
最初在寻找替代方案的时候,应该是2013年10月左右,找到了两个Chromium库:
chromeview
这个库封装的较好,但是有一个致命的bug是不能滚动。
README中声明:
Attemptingtoscrolltheview(byswipingafingeracrossthescreen)doesnotupdatethedisplayedimage.
However,internally,theviewisscrolled.
Thiscanbeseenbydisplayingastackofbuttonsandtryingtoclickonthetopmostone.
ThisissuemakesChromeViewmostlyunusableinproduction.
注:
这个库的README最新声明里面推荐了Crosswalk,作者还是很用心的。
android-chromium
这个库整体稳定,不存在上面的bug。
用它作为编辑器差不多一年,没有出现什么问题。
但在今年6、7月的时候,突然间发现在三星新出的几款平板上(搭载了Kitkat)表现为花屏,屏幕上出现了各种颜色的横条,无法进行编辑。
其他搭载了Kitkat的手机当时没有发现过什么问题。
这里说一下这个库,自从作者看到Kitkat使用Chromium后,作者就声明不再更新了,其实差不多一年前就已经不更新了。
这个库使用起来比较麻烦,需要自己再进行封装,甚至连onPageFinished都需要自己来做。
可以看到,上面的替代方案,到今年6、7月,实际上已经无法使用。
而且非组织维护的代码,通常都有些不可靠的意味。
于是不得不继续寻找替代方案。
终于在GoogleI/O上看到了希望——Crosswalk
Crosswalk入门
CSDN资讯:
Crosswalk的介绍Crosswalk官方地址
上面的链接可以看到Crosswalk的介绍,Crosswalk种种吹牛逼的描述我就不写了。
写一下我的使用感受:
不用费力搞什么自己封装了,直接像用WebView一样使用。
在使用android-chromium这个库时,不仅要自己封装API来方便使用,还要操心Chromium的初始化,甚至还需要在清单文件里写一堆关于Chromium的东西,用来帮助Chromium建立单独的进程(Crosswalk只会创建Chromium的线程,不需要独立进程)。
Crosswalk由组织维护,比个人维护强多了。
跟随最新的Chromium不断更新,js等不用担心有函数没法使用。
而且不断更新过程中,肯定也会修复以前存在的bug,稳定性也是不用担心的。
最新稳定版Crosswalk基于Chromium38编译。
注:
此库也可以配合Cordova(PhoneGap)使用。
OK,感受说完,上教程。
集成到应用中
下载zip包,解压后导入。
关联此Library。
在清单文件中写入下列权限
android:
name="android.permission.ACCESS_FINE_LOCATION"/>
android:
name="android.permission.ACCESS_NETWORK_STATE"/>
android:
name="android.permission.ACCESS_WIFI_STATE"/>
android:
name="android.permission.CAMERA"/>
android:
name="android.permission.INTERNET"/>
android:
name="android.permission.MODIFY_AUDIO_SETTINGS"/>
android:
name="android.permission.RECORD_AUDIO"/>
android:
name="android.permission.WAKE_LOCK"/>
android:
name="android.permission.WRITE_EXTERNAL_STORAGE"/>
注:
使用过程中,观察Logcat可以看到报需要蓝牙权限,可以不用管它,不添加蓝牙权限可以正常使用。
此外,使用XWalkView必须开启硬件加速。
XWalkViewneedshardwareaccelerationtorenderwebpages.Asaresult,theAndroidManifest.xmlofthecaller'sappmustbeappendedwiththeattribute"android:
hardwareAccelerated"anditsvaluemustbesetas"true".
android:
hardwareAccelerated:
Thedefaultvalueis"true"ifyou'veseteitherminSdkVersionortargetSdkVersionto"14"orhigher;otherwise,it's"false".
在清单文件Application中声明即可。
android:
name="android.app.Application"android:
label="XWalkUsers"
android:
hardwareAccelerated="true">
基本使用
Crosswalk中用来替代WebView的控件叫XWalkView。
layout文件写法
和其他自定义控件一样。
android:
id="@+id/activity_main"
xmlns:
android="
android:
layout_width="fill_parent"
android:
layout_height="fill_parent">
代码中使用
重中之重:
防止内存泄漏
和其他Android的控件不同,这个类需要监听系统事件。
例如:
生命周期、intent、Activityresult。
控件内置的Web引擎需要获取并处理这些信息。
并且当XWalkView不再需要使用的时候,在onDestroy方法中XWalkView必须显式的调用destroy方法,否则容易造成Web引擎的内存泄漏。
原文如下:
UnlikeotherAndroidviews,thisclasshastolistentosystemeventslikeapplicationlifecycle,intents,andactivityresult.Thewebengineinsidethisviewneedtogetandhandlethem.AndtheonDestroy()methodofXWalkViewMUSTbecalledexplicitlywhenanXWalkViewwon'tbeusedanymore,otherwiseitwillcausethememoryleakfromthenativesideofthewebengine.It'ssimilartothedestroy()methodofAndroidWebView.
这段文字来自XWalkView官方API文档。
奇怪的是官方的范例中并没有在意这些事情,直接像WebView一样使用,更没有使用destroy方法。
考虑到之前使用android-chromium库也是需要显式调用。
这里还是加上,避免内存泄漏。
importandroid.app.Activity;
importandroid.os.Bundle;
importorg.xwalk.core.XWalkView;
publicclassMyActivityextendsActivity{
privateXWalkViewmXWalkView;
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mXWalkView=(XWalkView)findViewById(R.id.activity_main);
mXWalkView.load("http:
//crosswalk-project.org/",null);
}
@Override
protectedvoidonPause(){
super.onPause();
if(mXWalkView!
=null){
mXWalkView.pauseTimers();
mXWalkView.onHide();
}
}
@Override
protectedvoidonResume(){
super.onResume();
if(mXWalkView!
=null){
mXWalkView.resumeTimers();
mXWalkView.onShow();
}
}
@Override
protectedvoidonDestroy(){
super.onDestroy();
if(mXWalkView!
=null){
mXWalkView.onDestroy();
}
}
@Override
protectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){
if(mXWalkView!
=null){
mXWalkView.onActivityResult(requestCode,resultCode,data);
}
}
@Override
protectedvoidonNewIntent(Intentintent){
if(mXWalkView!
=null){
mXWalkView.onNewIntent(intent);
}
}
}
loadUrl去哪了?
上面的代码中其实已经剧透了,使用load方法即可。
//url
mXWalkView.load("http:
//crosswalk-project.org/",null);
//thisloadsafilefromtheassets/directory
mXWalkView.load("file:
///android_asset/index.html",null);
publicvoidload(Stringurl,Stringcontent)
Loadawebpage/appfromagivenbaseURLoracontent.Ifurlisnulloremptyandcontentisnullorempty,thenthisfunctionwilldonothing.Ifcontentisnotnull,loadthewebpage/appfromthecontent.Ifcontentisnotnullandtheurlisnotset,return"about:
blank"ificallinggetUrl().Ifcontentisnull,trytoloadthecontentfromtheurl.ItsupportsURLschemeslike'http:
','https:
'and'file:
'.ItcanalsoloadfilesfromAndroidassets,e.g.'file:
///android_asset/'.
Parameters
urltheurlforwebpage/app.
contentthecontentforthewebpage/app.Couldbeempty.
WebViewClient?
对应WebView的WebViewClient,XWalkView中有XWalkResourceClient。
mXWalkView.setResourceClient(newXWalkResourceClient(mXWalkView){
@Override
publicvoidonLoadFinished(XWalkViewview,Stringurl){
super.onLoadFinished(view,url);
}
@Override
publicvoidonLoadStarted(XWalkViewview,Stringurl){
super.onLoadStarted(view,url);
}
});
调用JavaScript
不像WebView一样获取setting设置setJavaScriptEnabled为true才能执行。
Crosswalk可以直接执行js。
mXWalkView.load("javascript:
document.body.contentEditable=true;",null);
当然,按照Kitkat引入的方式,使用evaluateJavascript方法也是可以的。
(大神们推荐)
JavaScript回调Java
定义js回调接口
publicclassJsInterface{
publicJsInterface(){
}
@JavascriptInterface
publicStringsayHello(){
return"HelloWorld!
";
}
}
Caution:
Ifyou'vesetyourtargetSdkVersionto17orhigher,youmustaddthe@JavascriptInterfaceannotationtoanymethodthatyouwantavailabletoyourJavaScript(themethodmustalsobepublic).Ifyoudonotprovidetheannotation,themethodisnotaccessiblebyyourwebpagewhenrunningonAndroid4.2orhigher.
From
备注:
这里的@JavaScriptInterface所在的包是importorg.xwalk.core.JavascriptInterface;
XWalkView设置JavaScript可用且绑定对象
//绑定
mXWalkView.addJavascriptInterface(newJsInterface(),"NativeInterface");
调用html执行JavaScript或直接执行Javascript调用Java
mXWalkView.load("file:
///android_asset/index.html",null);
index.html源码:
href="#"onclick="clicked()">SayHello
functionclicked(){
alert(NativeInterface.sayHello());
}
/script>
高级使用
调试
Kitkat开始,Android提供了和Chrome联调功能。
可以很方便的在Chrome中调试WebView中的代码。
Crosswalk使用Chromium内核当然也具备这个功能。
开启调试的语句如下:
//turnondebugging
XWalkPreferences.setValue(XWalkPreferences.REMOTE_DEBUGGING,true);
对于Crosswalk来说,这个设置是全局的。
使用动画或者设置隐藏可见注意
默认XWalkView不能使用动画,甚至setVisibility也不行。
XWalkViewrepresentsanAndroidviewforwebapps/pages.ThusmostofattributesforAndroidviewarevalidforthisclass.Sinceitinternallyusesandroid.view.SurfaceViewforrenderingwebpagesbydefault,itcan'tberesized,rotated,transformedandanimatedduetothelimitationsofSurfaceView.Alternatively,ifthepreferencekeyANIMATABLE_XWALK_VIEWissettoTrue,XWalkViewcanbetransformedandanimatedbecauseTextureViewisintentionallyusedtorenderwebpagesforanimationsupport.Besides,XWalkViewwon'tberenderedifit'sinvisible.
开启动画模式:
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
//ANIMATABLE_XWALK_VIEWpreferencekeyMUSTbesetbeforeXWalkViewcreation.
XWalkPreferences.setValue(XWalkPreferences.ANIMATABLE_XWALK_VIEW,true);
setContentView(R.layout.animatable_xwview_layout);
}
@Override
publicvoidonDestroy(){
super.onDestroy();
//ResetthepreferenceforanimatableXWalkView.
XWalkPreferences.setValue(XWalkPreferences.ANIMATABLE_XWALK_VIEW,false);
}
由于设置也像调试一样是全局的,在onDestroy时记得关闭。
暂停JStimer
html代码
html>Ascriptonthispagestartsthisclock:
id="demo">
varmyVar=setInterval(function(){myTimer();},1000);
functionmyTimer()
{
vard=newDate();
vart=d.toLocaleTimeString();
document.getElementById("demo").innerHTML=t;
}
/script>
>
/html>
XWalkView对应方法:
mButton.setOnClickListener(newOnClickListener(){
@Override
publicvoidonClick(Viewv){
if(mXWalkView!
=
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 放弃 WebView 使用 Crosswalk 文本 编辑器
![提示](https://static.bdocx.com/images/bang_tan.gif)