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插件就成完了。