一、PhoneGap平台
前不久PhoneGap发布了1.0版本,这为移动开发大家族提供了又一个跨平台的解决方案。开发者只要有JavaScript、CSS3、Html5的基础就可以快速开发移动应用,并且一次开发支持iOS、iOS(xcode 4)、Android、WebOS、Blackberry、Symbian 六大平台。不过,JavaScript的速度虽然在近些年提高了100倍,其速度还是无法和原生代码相比。在编写复杂的业务逻辑时JavaScript显得力不从心。那么PhoneGap有没有办法解决这个问题呢?答案是肯定的。PhoneGap平台提供了插件功能,开发者可以将重量级的功能封装在原生代码开发的插件中,并将接口暴露给JavaScript,JavaScript在调用插件功能时都是非阻塞的,所以并不影响JavaScript层的性能。下面我们就看看如何编写和调用一个PhoneGap插件吧。
二、编写插件
由于要写原生代码,所以各个平台插件的编写略有不同。我们以Android为例吧。这个是PhoneGap官方的例子,原文网址:
http://wiki.phonegap.com/w/page/36753494/How%20to%20Create%20a%20PhoneGap%20Plugin%20for%20Android 需要翻墙。
1.插件功能
PhoneGap提供了文件读写的Api,但没有提供列出文件清单的功能。我们编写一个名为 DirectoryListingPlugin 的插件来实现列表SDCARD上文件的功能吧。
2.创建一个Android工程
如下图所示:
3.包含PhoneGap依赖
- 下载PhoneGap并解压
- 在工程根目录新建目录/libs
- 拷贝 phonegap.jar 到 /libs
4.实现插件类
代码:
- * Example of Android PhoneGap Plugin
- */
- package com.trial.phonegap.plugin.directorylisting;
- import java.io.File;
- import org.json.JSONArray;
- import org.json.JSONException;
- import org.json.JSONObject;
- import android.util.Log;
- import com.phonegap.api.Plugin;
- import com.phonegap.api.PluginResult;
- import com.phonegap.api.PluginResult.Status;
- /**
- * PhoneGap plugin which can be involved in following manner from javascript
- * <p>
- * result example -
- * {"filename":"/sdcard","isdir":true,"children":[{"filename":"a.txt"
- * ,"isdir":false},{..}]}
- * </p>
- *
- * <pre>
- * {@code
- * successCallback = function(result){
- * //result is a json
- *
- * }
- * failureCallback = function(error){
- * //error is error message
- * }
- *
- * DirectoryListing.list("/sdcard",
- * successCallback
- * failureCallback);
- *
- * }
- * </pre>
- *
- * @author Rohit Ghatol
- *
- */
- public class DirectoryListPlugin extends Plugin {
- /** List Action */
- public static final String ACTION = "list";
- /*
- * (non-Javadoc)
- *
- * @see com.phonegap.api.Plugin#execute(java.lang.String,
- * org.json.JSONArray, java.lang.String)
- */
- @Override
- public PluginResult execute(String action, JSONArray data, String callbackId) {
- Log.d("DirectoryListPlugin", "Plugin Called");
- PluginResult result = null;
- if (ACTION.equals(action)) {
- try {
- String fileName = data.getString(0);
- JSONObject fileInfo = getDirectoryListing(new File(fileName));
- Log
- .d("DirectoryListPlugin", "Returning "
- + fileInfo.toString());
- result = new PluginResult(Status.OK, fileInfo);
- } catch (JSONException jsonEx) {
- Log.d("DirectoryListPlugin", "Got JSON Exception "
- + jsonEx.getMessage());
- result = new PluginResult(Status.JSON_EXCEPTION);
- }
- } else {
- result = new PluginResult(Status.INVALID_ACTION);
- Log.d("DirectoryListPlugin", "Invalid action : " + action
- + " passed");
- }
- return result;
- }
- /**
- * Gets the Directory listing for file, in JSON format
- *
- * @param file
- * The file for which we want to do directory listing
- * @return JSONObject representation of directory list. e.g
- * {"filename":"/sdcard"
- * ,"isdir":true,"children":[{"filename":"a.txt"
- * ,"isdir":false},{..}]}
- * @throws JSONException
- */
- private JSONObject getDirectoryListing(File file) throws JSONException {
- JSONObject fileInfo = new JSONObject();
- fileInfo.put("filename", file.getName());
- fileInfo.put("isdir", file.isDirectory());
- if (file.isDirectory()) {
- JSONArray children = new JSONArray();
- fileInfo.put("children", children);
- if (null != file.listFiles()) {
- for (File child : file.listFiles()) {
- children.put(getDirectoryListing(child));
- }
- }
- }
- return fileInfo;
- }
- }
5.将插件类导出成jar 包
Eclipse中如下操作:
- 在要生成jar的项目上右击,选择菜单上的Export(导出)
- 导出类型选择Jar File
- 选择或者输入生成路径
- 选择要导出的类
6.实现JavaScript插件
- 创建一个名为DirectoryListing的类
- 创建一个成员函数list()
- 在成员函数中调用PhoneGap.exec(<<successCallback>>,<<failureCallback>>,<<Plugin Name>>,<<Action Name>>,<<Arguments Array>>);
- 将js文件保存为directorylisting.js
- *
- * @return Object literal singleton instance of DirectoryListing
- */
- var DirectoryListing = {
- /**
- * @param directory The directory for which we want the listing
- * @param successCallback The callback which will be called when directory listing is successful
- * @param failureCallback The callback which will be called when directory listing encouters an error
- */
- list: function(directory,successCallback, failureCallback) {
- return PhoneGap.exec(successCallback, //Success callback from the plugin
- failureCallback, //Error callback from the plugin
- 'DirectoryListPlugin', //Tell PhoneGap to run "DirectoryListingPlugin" Plugin
- 'list', //Tell plugin, which action we want to perform
- [directory]); //Passing list of args to the plugin
- }
- };
三、测试
1.创建一个PhoneGap应用 http://www.phonegap.com/start/#android
2.将 directorylisting.jar 加入工程依赖
3.将directorylisting.js放入到 /assets/www 目录下。
4.在 /res/xml/plugins.xml 文件中添加
5.在index.html中调用DirectoryListing.list
代码:
- <html>
- <head>
- <title>PhoneGap</title>
- </head>
- <body>
- <!-- Button -->
- <input disabled id="list-sdcard" type="button" value="List SDCard Contents" />
- <hr>
- <!-- Place Holder for placing the SD Card Listing -->
- <div id="result"></div>
- <hr>
- <script type="text/javascript" src="phonegap-1.0.0.js"></script>
- <script type="text/javascript" src="directorylisting.js"></script>
- <script type="text/javascript" >
- document.addEventListener('deviceready', function() {
- var btn = document.getElementById("list-sdcard");
- btn.onclick = function() {
- DirectoryListing.list( "/sdcard",
- function(r){printResult(r)},
- function(e){log(e)}
- );
- }
- btn.disabled=false;
- }, true);
- function printResult(fileInfo){
- var innerHtmlText=getHtml(fileInfo);
- document.getElementById("result").innerHTML=innerHtmlText;
- }
- function getHtml(fileInfo){
- var htmlText="<ul><li>"+fileInfo.filename;
- if(fileInfo.children){
- for(var index=0;index<fileInfo.children.length;index++){
- htmlTexthtmlText=htmlText+getHtml(fileInfo.children[index]);
- }
- }
- htmlTexthtmlText=htmlText+"</li></ul>";
- return htmlText;
- }
- </script>
- </body>
- </html>