http://www.oschina.net/question/163910_27119
一、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.实现插件类
代码:
001 |
/** |
002 |
*
Example of Android PhoneGap Plugin |
003 |
*/ |
004 |
package com.trial.phonegap.plugin.directorylisting; |
005 |
006 |
007 |
import java.io.File; |
008 |
009 |
010 |
import org.json.JSONArray; |
011 |
import org.json.JSONException; |
012 |
import org.json.JSONObject; |
013 |
014 |
015 |
import android.util.Log; |
016 |
017 |
018 |
import com.phonegap.api.Plugin; |
019 |
import com.phonegap.api.PluginResult; |
020 |
import com.phonegap.api.PluginResult.Status; |
021 |
022 |
023 |
/** |
024 |
*
PhoneGap plugin which can be involved in following manner from javascript |
025 |
*
<p> |
026 |
*
result example - |
027 |
*
{"filename":"/sdcard","isdir":true,"children":[{"filename":"a.txt" |
028 |
*
,"isdir":false},{..}]} |
029 |
*
</p> |
030 |
* |
031 |
*
<pre> |
032 |
*
{@code |
033 |
*
successCallback = function(result){ |
034 |
*
//result is a json |
035 |
* |
036 |
*
} |
037 |
*
failureCallback = function(error){ |
038 |
*
//error is error message |
039 |
*
} |
040 |
* |
041 |
*
DirectoryListing.list("/sdcard", |
042 |
*
successCallback |
043 |
*
failureCallback); |
044 |
* |
045 |
*
} |
046 |
*
</pre> |
047 |
* |
048 |
*
@author Rohit Ghatol |
049 |
* |
050 |
*/ |
051 |
public class DirectoryListPlugin extends Plugin
{ |
052 |
/**
List Action */ |
053 |
public static final String
ACTION = "list" ; |
054 |
055 |
056 |
/* |
057 |
*
(non-Javadoc) |
058 |
* |
059 |
*
@see com.phonegap.api.Plugin#execute(java.lang.String, |
060 |
*
org.json.JSONArray, java.lang.String) |
061 |
*/ |
062 |
@Override |
063 |
public
PluginResult execute(String action, JSONArray data, String callbackId) { |
064 |
Log.d("DirectoryListPlugin",
"Plugin Called"); |
065 |
PluginResult
result = null; |
066 |
if
(ACTION.equals(action)) { |
067 |
try
{ |
068 |
String
fileName = data.getString(0); |
069 |
JSONObject
fileInfo = getDirectoryListing(new File(fileName)); |
070 |
Log |
071 |
.d("DirectoryListPlugin",
"Returning " |
072 |
+
fileInfo.toString()); |
073 |
result
= new PluginResult(Status.OK, fileInfo); |
074 |
}
catch (JSONException jsonEx) { |
075 |
Log.d("DirectoryListPlugin",
"Got JSON Exception " |
076 |
+
jsonEx.getMessage()); |
077 |
result
= new PluginResult(Status.JSON_EXCEPTION); |
078 |
} |
079 |
}
else { |
080 |
result
= new PluginResult(Status.INVALID_ACTION); |
081 |
Log.d("DirectoryListPlugin",
"Invalid action : " + action |
082 |
+
" passed"); |
083 |
} |
084 |
return
result; |
085 |
} |
086 |
087 |
088 |
/** |
089 |
*
Gets the Directory listing for file, in JSON format |
090 |
* |
091 |
*
@param file |
092 |
*
The file for which we want to do directory listing |
093 |
*
@return JSONObject representation of directory list. e.g |
094 |
*
{"filename":"/sdcard" |
095 |
*
,"isdir":true,"children":[{"filename":"a.txt" |
096 |
*
,"isdir":false},{..}]} |
097 |
*
@throws JSONException |
098 |
*/ |
099 |
private JSONObject
getDirectoryListing(File file) throws JSONException
{ |
100 |
JSONObject
fileInfo = new JSONObject(); |
101 |
fileInfo.put( "filename" ,
file.getName()); |
102 |
fileInfo.put( "isdir" ,
file.isDirectory()); |
103 |
if (file.isDirectory())
{ |
104 |
JSONArray
children = new JSONArray(); |
105 |
fileInfo.put( "children" ,
children); |
106 |
if ( null !=
file.listFiles()) { |
107 |
for (File
child : file.listFiles()) { |
108 |
children.put(getDirectoryListing(child)); |
109 |
} |
110 |
} |
111 |
} |
112 |
return fileInfo; |
113 |
} |
114 |
} |
Eclipse中如下操作:
- 在要生成jar的项目上右击,选择菜单上的Export(导出)
- 导出类型选择Jar File
- 选择或者输入生成路径
- 选择要导出的类
6.实现JavaScript插件
- 创建一个名为DirectoryListing的类
- 创建一个成员函数list()
- 在成员函数中调用PhoneGap.exec(<<successCallback>>,<<failureCallback>>,<<Plugin Name>>,<<Action Name>>,<<Arguments Array>>);
- 将js文件保存为directorylisting.js
代码:
01 |
/** |
02 |
* |
03 |
*
@return Object literal singleton instance of DirectoryListing |
04 |
*/ |
05 |
var
DirectoryListing = { |
06 |
/** |
07 |
*
@param directory The directory for which we want the listing |
08 |
*
@param successCallback The callback which will be called when directory listing is successful |
09 |
*
@param failureCallback The callback which will be called when directory listing encouters an error |
10 |
*/ |
11 |
list:
function(directory,successCallback, failureCallback) { |
12 |
return PhoneGap.exec(successCallback, //Success
callback from the plugin |
13 |
failureCallback, //Error
callback from the plugin |
14 |
'DirectoryListPlugin' , //Tell
PhoneGap to run "DirectoryListingPlugin" Plugin |
15 |
'list' , //Tell
plugin, which action we want to perform |
16 |
[directory]); //Passing
list of args to the plugin |
17 |
} |
18 |
}; |
三、测试
1.创建一个PhoneGap应用 http://www.phonegap.com/start/#android
2.将 directorylisting.jar 加入工程依赖
3.将directorylisting.js放入到 /assets/www 目录下。
4.在 /res/xml/plugins.xml 文件中添加
1 |
< plugin name = "DirectoryListPlugin" |
2 |
value = "com.trial.phonegap.plugin.directorylisting.DirectoryListPlugin" /> |
5.在index.html中调用DirectoryListing.list
代码:
01 |
<!DOCTYPE
HTML> |
02 |
<html> |
03 |
<head> |
04 |
<title>PhoneGap</title> |
05 |
</head> |
06 |
<body> |
07 |
<!--
Button --> |
08 |
<input
disabled id= "list-sdcard" type= "button" value= "List
SDCard Contents" /> |
09 |
<hr> |
10 |
|
11 |
<!--
Place Holder for placing
the SD Card Listing --> |
12 |
<div
id= "result" ></div> |
13 |
|
14 |
<hr> |
15 |
|
16 |
<script
type= "text/javascript" src= "phonegap-1.0.0.js" ></script> |
17 |
<script
type= "text/javascript" src= "directorylisting.js" ></script> |
18 |
<script
type= "text/javascript" > |
19 |
document.addEventListener( 'deviceready' , function ()
{ |
20 |
var btn
= document.getElementById( "list-sdcard" ); |
21 |
btn.onclick
= function ()
{ |
22 |
DirectoryListing.list( "/sdcard" , |
23 |
function (r){printResult(r)}, |
24 |
function (e){log(e)} |
25 |
); |
26 |
} |
27 |
btn.disabled= false ; |
28 |
}, true ); |
29 |
|
30 |
|
31 |
function printResult(fileInfo){ |
32 |
var innerHtmlText=getHtml(fileInfo); |
33 |
document.getElementById( "result" ).innerHTML=innerHtmlText; |
34 |
} |
35 |
|
36 |
function getHtml(fileInfo){ |
37 |
var htmlText= "<ul><li>" +fileInfo.filename; |
38 |
if (fileInfo.children){ |
39 |
|
40 |
for ( var index=0;index<fileInfo.children.length;index++){ |
41 |
htmlText=htmlText+getHtml(fileInfo.children[index]); |
42 |
} |
43 |
} |
44 |
htmlText=htmlText+ "</li></ul>" ; |
45 |
return htmlText; |
46 |
|
47 |
} |
48 |
</script> |
49 |
|
50 |
</body> |
51 |
</html> |
至此,一个PhoneGap Android插件就成完了。