`

PhoneGap android方向解析

 
阅读更多

PhoneGap源码解析

<wbr></wbr>

<wbr></wbr>

Phonegap的核心是插件。在phonegap的概念中,一切调用native功能,都被封装成插件(plugin),由PlugInManager来管理。而在PhoneGap的使用方法中,PlugInManager是由重写过的Activity,即DroidGap来调用的。

<wbr></wbr>

本文主要涉及到的类是PlugInManager,PlugIn,DroidGap, CallbackServer,主要探讨phonegap源码的实现和可供我们结合使用的方式。


1.

DroidGap继承于PhonegapActivity,而PhonegapActivity继承于activity

<wbr></wbr>

PhonegapActivity是一个抽象类,其中方法不多,列举如下:

<wbr></wbr>

abstract public void sendJavascript(String statement);

abstract public void startActivityForResult(IPlugin command, Intent intent, int requestCode);

abstract public void loadUrl(String url);

abstract public void setActivityResultCallbac<wbr>k(IPlugin plugin);</wbr>

abstract public void setActivityResultCallbac<wbr>k(IPlugin plugin);</wbr>

<wbr></wbr>

其中sendJavascriptloadUrlphonegap的关键方法。还有两个关键的继承类,GapViewClientGapClient


<wbr></wbr>

sendJavascript会被具体的PlugIn回调,例如storage这个插件,在startPlaying方法中,会调用自己的sendJavascript,然后这个sendJavascript会继续调用DroidGapsendJavascript,然后继续调用CallbackServersendJavascript方法,添加到CallbackServerjavascript linkedlist中去。

<wbr></wbr>

loadUrl事实上是调用了对应的webviewloadUrl,做了一些额外的处理。loadUrl中调用了loadUrlIntoView方法,其中在加载url之前,初始化了CallbackServer, pluginManager,还为webview设置了超时时间。

<wbr></wbr>

DroidGap中,GapViewClient是对WebviewClient的继承。

<wbr></wbr>

主要是针对拨打电话,调用地图,发送邮件等本Intent的方式进行拦截和调用。这部分代码我们可以直接copy过来使用。

<wbr></wbr>

DroidGap中,GapClient是对WebChromeClient的继承。

onJsAlertonJsConfirm方法中,使用Dialog来代替js的默认实现。

onJsPrompt中,对满足以下条件

<wbr></wbr>

<wbr>(url.startsWith("file://") || url.indexOf(this.ctx.baseUrl) == 0 || isUrlWhiteListed(url))</wbr>

1).file://开头的本地文件

2).在请求的url域名内

3).在配置的url白名单内,白名单是一个配置文件,通过addWhiteListEntry添加。放在xml目录下的phonegap.xml文件。默认配置了http://127.0.0.1

<wbr></wbr>

并且满足例如"gap:"等情况。进行了自行重写。

<wbr></wbr>

重写条件如下:

1)满足"gap:"开头的,调用plugInManager进行处理。此时每个gap:后面的内容会对应一个具体的调用本地操作的功能。例如摄像头,本地存储等。

2)满足"gap_poll:"开头的,调用callbackServer.getJavascript();

3)满足"gap_callbackServer:"开头的,调用callbackServer.restartServer()等操作。

4)满足"gap_init:"开头的,将webview设置为不可见

<wbr></wbr>

其他情况,依然是以一个dialog形式弹出。

<wbr></wbr>

重点说一下重写条件1)

调用PlugInManager的时候,每次都会重新开启一个线程,在开启线程前还做了一次同步检查,保证同一时刻同一个插件只被调用一次。在线程中,调用对一个PlugIn,执行PlugInexec方法,执行具体功能。执行完成之后,返回一个PluginResult。其中以status标示了本地功能调用结果。如果调用成功或者无结果(也可以说是另一方面的调用成功,比如notifacation这种功能),则调用DroidGapsendJavaScript方法,通知给CallbackServer

<wbr></wbr>

另外还重写了onPageFinish等一系列方法,我们都可以参考。

<wbr></wbr>

按我的理解,在这个部分的写法的好处,从模式上讲是将本地功能模块化,明晰化,封装的比较好,各自调用自己的功能,从执行效率上讲避免了主线程执行功能,但是在异步线程中操作数据库等功能,会不会引起问题,这个可能也是未来我们结合phonegap的方式来处理自己的程序需要注意的地方。

<wbr></wbr>

2.

另外一个比较重要的工具类是CallbackServer,这也是phonegap框架后来改名为CallBack的原因。它是一个客户端本地实现的XHRServer。在调用完js中的代码,执行完本地的功能后,需要给js发送一个反馈,也就是调用sendJavaScript方法。

<wbr></wbr>

初始化CallbackServer的时候,会建立一个泛型为StringLinkedList,用于保存javascript代码。CallbackServer在外部被调用最多的sendJavascript方法,实现中就是将发送过来的Js语句,添加到这个LinkedList中。

如果要加载的url不是以file://开头,就会建立一个新的线程,CallbackServer本身是实现了Runnable接口的,这个线程就以this作为参数。同时start这个线程。

所以,在整个CallbackServer中,最核心的方法凸显出来了,就是Run

<wbr></wbr>

Run方法中,建立了一个ServerSocket,将自己作为一个服务器来接收请求。

LinkedList中有没有处理完的返回结果的时候,就会把链表中的最先进来的提出来,返回给客户端。没有请求来,则10秒钟返回一个空的回复,以维持XHRServer

<wbr></wbr>

PhoneGap.js中,PhoneGap.JSCallbackPolling会被setTimeout(1)作为轮询,来访问这个CallBackServer,监听js需要处理的内容。

我个人对这个地方有些疑问,因为这么短时间的轮询,虽然是本地执行,但是会不会有效率问题,需要真正进入开发实战和测试后才能体现。

<wbr></wbr>

<wbr></wbr>

3.

至此,综合12phonegap对于本地方法的调用的结构已经清晰。

在对javascript的执行上,phonegap给我们提供了一个有别于addJavaScriptInterface<wbr></wbr>的另外一种方法。在phonegap1.0之前,它就是采用原生的addJavaScriptInterface<wbr></wbr>这种方法进行调用,后来才改成xhrserver的方式。原因可能是addJavaScripteInterface是一种同步调用,对效率较低或执行时间较长的js语句,会产生阻塞。

在对本地方法的调用上,phonegap给我们提供了一个用js来调用java的插件框架,我们可以这种思路拆分出来,并且进行优化,我目前觉得phonegap对插件的使用上还是比较死板,本地方法的调用都集成在phonegap.js中,实际上还是很难由用户添加新功能,如果不改动此主要js文件的情况下。如果配合反射等手段,我们可能可以做到真正的插件化本地调用,用在我们的代码中。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics