Android WebView呼叫Javascript填坑记

作为誓死效忠大安卓帝国的程序狗,我一般不写技术类文章。
  你们翻翻我的文章就会发现,我还真不像技术流的。
  不过最近搞一个安卓的坑,搞得非常蛋疼,于是打算纪录下来。

坑是这样的:我有一个WebView,里面有一个写字区域,然后我要在写字的同时呼叫里面的JS。
  在iOS上这事挺容易整的,比如这样(obj-C为例):

NSString *hasRange =
    [self stringByEvaluatingJavaScriptFromString:@"MobileWriter.hasRange()"];

但在大安卓帝国,这事就有点蛋疼了。

在KitKat上,WebView有个接口名叫evaluateJavascript,从而事情是这样的:

evaluateJavascript("MobileWriter.hasRange();", resultCallback);

这货看上去和iOS上差不多,但已经有点讨厌了:它是Callback机制的,不像iOS上直接拿结果。
  但,这还算好的,如果不是KitKat,也就是4.4之前的Android,你连这个接口都没有,于是只能这样:

loadUrl("javascript:MobileWriter.hasRange();");

这个就很蛋疼了,因为没有callback,你必须在JS运行结束后,让JS去调用一个指定的对象,从而通过这个对象来获得回调,比如下面这样:

(In Java)
addJavascriptInterface(new JavascriptDelegate () {
    @JavascriptInterface
    public void jsCallback (String result) {
        Log.i("Editor", "Blablabla...");
    }
}, "AndroidHost");

(In Javascript)
MobileWriter.hasRange = function () {
    "Blablabla..."
    if (AndroidHost && AndroidHost.jsCallback) {
        AndroidHost.jsCallback('Mission Complete.');
    }
};

看着是不是就很蛋疼?
  但,这根本不算事,挺Easy的,只要J-J两端协议定好,这都不叫事儿。
  麻烦的是下面这个问题:
  每次你在Java端使用loadUrl的时候,在4.4以下的安卓上都会引发WebView的页面重新载入事件(而且这个你还没法通过重载WebViewClient的shouldOverrideUrlLoading方法来阻止),从而引发系统的clearHelpers,这货则会调用clearTextEntry并最终调用到hideSoftKeyboard。
  这个貌似看上去没什么,但实际上却很糟糕,因为这会导致两个问题:

  1. SoftKeyboard会自动消失(hideSoftKeyboard);
  2. Contextual Menu和相关选区会自动消失(clearTextEntry)。

也就是说,如果你在输入的时候就要调用JS的话,那么只要你调用了JS,输入状态就自动消失,键盘没了,选区没了,你得重新开始选择。
  这事就很蛋疼了。
  4.4为什么通过调用loadUrl来调用JS不会有这个问题?因为如果你调用的是javascript协议从而也就是调用js函数的话,其实4.4下面走的是上面提到的evaluateJavascrpt,当然安全了。

解决这个问题的方法,一个是用反射调用android.webkit.BrowserFrame.stringByEvaluatingJavaScriptFromString(),这个比较蛋疼。
  另一个,则是设法通知JS我Java端有事件了,然后让JS调用JavascriptDelegate插入的Delegate对象,并从这个对象获取当前要做的事件,并执行。

第一个方法比较霸气,直接用反射,相当犀利,但我不确定能否通过安检(不过国内App反正也没啥检查,应该不慌。GoogleAppStore是否允许我这么玩我就不知道了)。
  第二个方法比较温和,没这么霸气,但缺点是你得加一个同步锁,避免操作不同步导致问题——WebView中的JS是跑在另一根线程上的,这种频繁的线程间相互调用回调的方法安全性是个问题。
  至于说通知JS应该要召唤Delegate的方法嘛,当然不能傻傻地用loadUrl了。你可以小小地微调一下WebView的尺寸,引发JS端的window.onresize事件,然后就可以让JS端去调用Java端了。
  或者另一个比较蛋疼的方法是JS端开一个Timeout甚至Interval,这个有点网站开发早期的轮询了,但个人不建议这么做,毕竟是手机端,毕竟是轮询,还是要考虑资源消耗的。
  至于说有没有别的通知手段,这个暂时没想到。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,565评论 25 707
  • 前言 总结 Android WebView 常用的相关知识点,令包含以下干货内容分析:Js注入漏洞、WebView...
    無名小子的杂货铺阅读 69,653评论 17 169
  • WebView·开车指南 2016-08-31BugDev 北京市东城区首席Bug布道师开山之作,一整月交通事故血...
    53c021c38a1d阅读 798评论 0 1
  • WebView·开车指南 目录 WebView简介 WebView基本使用 WebView常用方法 WebSett...
    南城的人阅读 4,710评论 0 19
  • dear leader: 我是运维组的谭雁宏,很幸运在2016年8月3日入职成为公司的试用期员工,并担任运维工程师...
    nicksors阅读 7,800评论 0 8