引言
Cordova(PhoneGap)采用的是HTML5+JavaScript混合模式来开 发移动手机APP,因此当页面需要获取手机内部某些信息时(例如:联系人信息,坐标定位,短信等),程序就需要调用手机内部的API跟页面进行信息交换。 Cordova 特别为此定制了完善的解决方案,以方便用户进行程序编辑。在这一章里将为大家逐一介绍Cordova与Actitity通讯的实现原理。
目录
二、页面通过 cordova.exec 函数调用 CordovaPlugin 插件
四、页面通过CordovaPlugin插件调用Activity开发实例
一、CordovaPlugin类简介
CordovaPlugin是Cordova插件的父类,用户自定义的插件必须继承父类,它的主要常用属性如下
属性 | 详细说明 |
CordovaWebView | 视图管理器,当中包括PluginManager、CordovaWebViewEngine、ICordovaCookieManager等多个对象,用于管理界面渲染,视图加载过程中的生命周期 |
CordovaInterface | 定义startActivityForResult、setActivityResultCallback等主要方法,获取调用上下文中的Activity对象 |
CordovaPreferences | 用于管理bundle中的属性值 |
表格1.1
CordovaPlugin的常用方法如下
方法 | 详细说明 |
void privateInitialize(String serviceName, CordovaInterface cordova, CordovaWebView webView, CordovaPreferences preferences) | 插件初始化时执行,用于定义service名称,cordovaInterface接口,CodovaWebView视图,CordovaPreferences 属性等值 |
boolean execute(String action, String rawArgs, CallbackContext callbackContext) | 在开发插件时,用户的自定义方法,当页面调用插件时系统首先将会运行此方法 |
boolean execute(String action, JSONArray args, CallbackContext callbackContext) | 同上 |
boolean execute(String action, CordovaArgs args, CallbackContext callbackContext) | 同上 |
void onActivityResult(int requestCode, int resultCode, Intent intent) | 在开发插件时,用户的自定义方法,插件调用startActivityForResult后的回调函数。 |
String getServiceName() | 获取在config文件中该服务的名称 |
Boolean shouldAllowRequest(String url) | 判断是否允许此请求 |
Boolean shouldAllowNavigation(String url) | 判断是否允许此导航 |
Boolean shouldOpenExternalUrl(String url) | 判断是否打开外部链接 |
boolean onReceivedHttpAuthRequest(CordovaWebView view, ICordovaHttpAuthHandler handler, String host, String realm) | |
boolean onReceivedClientCertRequest(CordovaWebView view, ICordovaClientCertRequest request) |
表格1.2
CordovaPlugin的详细解析可参考官网
二、页面调用 CordovaPlugin 插件实例
大概了解 CordovaPlugin 类的使用方法后,下面为大家介绍一下页面调用插件的例子。首先打开文件res/xml/config.xml为插件进行配置。
<preference/>可用于运行环境中的常用参数,例如:全屏设置,滚动条设置,背景色设置等等
<preference name="Fullscreen" value="true" />
<preference name="DisallowOverscroll" value="true"/>
<preference name="BackgroundColor" value="0xff0000ff"/>
<feature></feature>节点用于设置插件描述,feature的name属性是设置插件的唯一标示,在页面调用插件时将通过name找到此插件
在开发插件时,先为此插件添加一个<feature>节点,在<param>中绑定插件的后台执行文件ShowMessagePlugin.java
<param name="android-package" value="org.apache.cordova.showmessage.ShowMessagePlugin" />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
<?
xml
version
=
'1.0'
encoding
=
'utf-8'
?>
<
widget
id
=
"com.sun.androidapp"
version
=
"0.0.1"
xmlns
=
"http://www.w3.org/ns/widgets"
xmlns:cdv
=
"http://cordova.apache.org/ns/1.0"
>
<!--设置运行环境中的参数值 -->
<
preference
name
=
"loglevel"
value
=
"DEBUG"
/>
<!-- 插件描述 -->
<
feature
name
=
"Whitelist"
>
<
param
name
=
"android-package"
value
=
"org.apache.cordova.whitelist.WhitelistPlugin"
/>
<
param
name
=
"onload"
value
=
"true"
/>
</
feature
>
<
feature
name
=
"ShowMessage"
>
<
param
name
=
"android-package"
value
=
"org.apache.cordova.showmessage.ShowMessagePlugin"
/>
</
feature
>
<
allow-intent
href
=
"market:*"
/>
<!-- 该APP名称 -->
<
name
>AndroidTest</
name
>
<!-- APP描述 -->
<
description
>
A sample Apache Cordova application that responds to the deviceready event.
</
description
>
<!-- 作者信息描述 -->
<
author
email
=
"dev@cordova.apache.org"
href
=
"http://cordova.io"
>
Apache Cordova Team
</
author
>
<!-- 默认启动页面 -->
<
content
src
=
"index.html"
/>
<!-- 指定app可进行通信的域名,*为所有 -->
<
access
origin
=
"*"
/>
<!-- App默认只请允许通过手机端直接打开,若想通过网站,SMS等方式调用APP,则需要设置allow-intent配置 -->
<
allow-intent
href
=
"http://*/*"
/>
<
allow-intent
href
=
"https://*/*"
/>
<
allow-intent
href
=
"tel:*"
/>
<
allow-intent
href
=
"sms:*"
/>
<
allow-intent
href
=
"mailto:*"
/>
<
allow-intent
href
=
"geo:*"
/>
</
widget
>
|
建立org.apache.cordova.showmessage.ShowMessagePlugin类,且继承CordovaPlugin基类,并实现
bool execute(action,args,callbackcontext) 方法。当页面调用此插件时,默认执行此方法。
action 是唯一标识符,系统可根据不同的action进行不同的操作。
args是页面传入的参数,支持String, JsonArray,CordovaArgs 等三种不同的类型。
callbackcontext是系统的上下文,当完成操作后调用callbackcontext.success(支持多类型参数)方法,表示插件操作已完成,并把参数返还到页面。最终返回true代表插件执行成功,false代表执行失败
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
package
org.apache.cordova.showmessage;
public
class
ShowMessagePlugin
extends
CordovaPlugin {
@Override
public
boolean
execute(String action,JSONArray args,CallbackContext context)
throws
JSONException{
if
(action.equals(
"mydream"
)){
String msg=args.getString(
0
)+
"'s dream is to become a "
+args.getString(
1
);
context.success(msg);
return
true
;
}
return
false
;
}
}
|
在 cordova.js 包中,最常用的是 cordova.exec(success,failed,service,action,args)函数,页面正是通过此函数调用插件。
success 用于绑定插件执行成功后回调的回调函数
failed用于绑定执行失败的回调函数
service与config.xml配置文件中feature字节的name属性相对应
action与ShowMessagePlugin对象boolean excute方法中action参数对应,用于分辨插件执行的方法类型,插件可根据action类型的不同作出分类处理。
args为输入参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
Name: <
input
type
=
"text"
id
=
"txt1"
/>
Dream:<
input
type
=
"text"
id
=
"txt2"
/>
<
input
type
=
"button"
onclick
=
"btnclick()"
name
=
"btn"
value
=
"Click"
/> <
br
/>
<
label
id
=
"label"
></
label
>
<
script
type
=
"text/javascript"
>
function btnclick(){
var name=$("#txt1").val();
var dream=$("#txt2").val();
//通过 cordova.exec (success,failed,serviceName,action,args)函数调用插件
cordova.exec(success,failed,"ShowMessage","mydream",[name,dream])
}
//成功调用插件,获取返回值后的页面处理函数
function success(result){
if(result!=null)
$("#label").html(result);
else
alert("no message");
}
//调用失败后的处理函数
function failed(msg){
......
}
</
script
>
|
测试结果
三、CordovaInterface接口说明
CordovaInterface 接口默认是由 CordovaInterfaceImpl 类实现的,当中包括了一个Activity对象。当打开APP时 Cordova 会默认启动此 Activity 以承载 Cordova 核心引擎对程序进行管理。ExecutorService 则负责对象对线程池进行管理,PluginManager则负责对插件进行管理,CordovaPlugin则是Cordova插件的父类,所有插件都必须继承CordovaPlugin。
属性 | 详细说明 |
Activity | 打开APP时 Cordova 会默认启动此 Activity 以承载 Cordova 核心引擎对程序进行管理 |
ExecutorService | 对线程池进行管理 |
PluginManager | 插件管理器,用于管理插件的生成,运行,结束等生命周期 |
CordovaPlugin | 通过startActivityForResult方法绑定CordovaPlugin插件 |
ActivityResultHolder | 内部类,封装了requestCode, resultCode, intent等对象 |
表格2.1
CordovaInterfaceImpl定义了三个最常用方法
方法 | 详细说明 |
void startActivityForResult(CordovaPlugin command, Intent intent, int requestCode) | 绑定CordovaPlugin参数,并调用Activity对象的startActivityForResult(intent, requestCode)方法,根据 intent 绑定值跳转到对应的activity |
void setActivityResultCallback(CordovaPlugin plugin) | 激发CordovaPlugin对象的onActivityResult事件 |
boolean onActivityResult(int requestCode, int resultCode, Intent intent) | 封装Acticity对象的onActivityResult回调函数, 激发CordovaPlugin对象的onActivityResult事件 |
表格2.2
四、页面通过CordovaPlugin插件调用Activity开发实例
类似于第一节实例,在页面通过cordova.exec(success,failed,service,action,args)方法调用插件,返回时调用success函数进行处理显示结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
出游省份:
<
select
id
=
"select1"
>
<
option
value
=
'1'
selected
=
'selected'
>黑龙江</
option
>
<
option
value
=
'2'
>吉林</
option
>
<
option
value
=
'3'
>辽宁</
option
>
</
select
>
<
input
type
=
"button"
onclick
=
"btnclick()"
name
=
"btn"
value
=
"查找"
/> <
br
/>
路线景点:
<
label
id
=
"label"
></
label
><
br
/>
<
script
type
=
"text/javascript"
>
function btnclick(){
var province=$("#select1").val();
//通过 cordova.exec (success,failed,serviceName,actionName,args)函数调用插件
cordova.exec(success,null,"ShowMessage","showMessage",[province]);
}
//成功调用插件,获取返回值后的页面处理函数
function success(result){
if(result!=null)
$("#label").html(result);
else
alert("no message");
}
</
script
>
|
插 件通过判断action参数判断进行不同的处理,然后通过Intent对象绑定将要启动的Activity,最后通过CordovaInterface中 的startActivityForResult(cordovaPlugin,intent,int)方法启动该Activity。当 Activity 结束后,系统将调用回调函数 onActivityResult(int requestCode, int resultCode, Intent intent)
在此说明一下Intent类的用途,此类主要用于绑定当前的活动与子活动之间关系,当中包含6种构造函数。
1、Intent() 空构造函数
2、Intent(Intent o) 拷贝构造函数
3、Intent(String action) 指定action类型的构造函数
4、Intent(String action, Uri uri) 指定Action类型和Uri的构造函数,URI主要是结合程序之间的数据共享ContentProvider
5、Intent(Context packageContext, Class<?> cls) 传入组件的构造函数,也就是此例子中使用到的
6、Intent(String action, Uri uri, Context packageContext, Class<?> cls) 前两种结合体
Intent 类中封装了一个Bundle 对象 mExtras,可用于主活动与子活动之间传值,系统可通过 putExtra 方法把参数传入mExtras, 也可通过 getShortExtra、getIntExtra、getBooleanExtra、getByteExtra 等多个方法从mExtras 获取参数值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public
class
ShowMessagePlugin
extends
CordovaPlugin {
private
CallbackContext context;
@Override
public
boolean
execute(String action,JSONArray args,CallbackContext context)
throws
JSONException{
this
.context=context;
//根据action判断调用方法
if
(action.equals(
"showMessage"
)){
//通过Intent绑定将要调用的Activity
Intent intent=
new
Intent(
this
.cordova.getActivity(),SpotActivity.
class
);
//加入将要传输到activity中的参数
intent.putExtra(
"province"
, args.getString(
0
));
//启动activity
this
.cordova.startActivityForResult(
this
, intent,
0
);
}
return
true
;
}
@Override
public
void
onActivityResult(
int
requestCode,
int
resultCode, Intent intent) {
// 根据resultCode判断处理结果
if
(resultCode==Activity.RESULT_OK){
String spot=intent.getStringExtra(
"spot"
);
context.success(spot);
}
}
}
|
Activity 被触发后先通过 setContentView 方法绑定视图,再从intent 对象中获取输入参数进行处理。
完成操作后,通过 Activity 类 setResult(int resultCode, Intent data) 方法绑定返回值,其中resultCode可被 cordovaPlugin 插件用作判断返回值的处理结果。
最后调用 Activity 对象的 finish 方法关闭 SpotActivity,把返回值回传到 CordovaPlugin。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
public
class
SpotActivity
extends
Activity{
private
CheckBox chk1,chk2,chk3;
@Override
public
void
onCreate(Bundle savedInstanceState){
super
.onCreate(savedInstanceState);
//绑定视图
setContentView(R.layout.goods_list);
//从intent中获取输入参数
Integer province=Integer.parseInt(
this
.getIntent().getStringExtra(
"province"
));
setSpots(province);
}
private
void
setSpots(Integer n){
this
.chk1=(CheckBox)
this
.findViewById(R.id.checkBox1);
this
.chk2=(CheckBox)
this
.findViewById(R.id.checkBox2);
this
.chk3=(CheckBox)
this
.findViewById(R.id.checkBox3);
switch
(n){
case
1
:
chk1.setText(
"漠河"
);
chk2.setText(
"北极村"
);
chk3.setText(
"九曲十八湾"
);
break
;
case
2
:
chk1.setText(
"长白山"
);
chk2.setText(
"雾凇岛"
);
chk3.setText(
"朝鲜自治州"
);
break
;
case
3
:
chk1.setText(
"鸭绿江"
);
chk2.setText(
"笔架山"
);
chk3.setText(
"凤凰山"
);
break
;
default
:
break
;
}
}
public
void
btn_onClick(View view){
String spot=
""
;
if
(chk1.isChecked())
spot+=chk1.getText();
if
(chk2.isChecked())
spot+=
" "
+chk2.getText();
if
(chk3.isChecked())
spot+=
" "
+chk3.getText();
//通过setResult绑定返回值
Intent intent=
new
Intent();
intent.putExtra(
"spot"
,spot);
setResult(RESULT_OK,intent);
//关闭该activity,把返回值传回到cordovaPlugin插件
this
.finish();
}
}
|
Activity 视图
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
LinearLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
android:layout_alignParentBottom
=
"true"
android:orientation
=
"vertical"
>
<
TextView
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:text
=
"选择景点"
android:layout_marginTop
=
"80dp"
/>
<
CheckBox
android:id
=
"@+id/checkBox1"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
/>
<
CheckBox
android:id
=
"@+id/checkBox2"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
/>
<
CheckBox
android:id
=
"@+id/checkBox3"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
/>
<
Button
android:id
=
"@+id/button1"
style
=
"?android:attr/buttonStyleSmall"
android:layout_width
=
"wrap_content"
android:layout_height
=
"40dp"
android:text
=
"确认"
android:layout_marginTop
=
"20dp"
android:onClick
=
"btn_onClick"
/>
</
LinearLayout
>
|
activity 关闭后,cordovaPlugin 插件将 调用回调函数 onActivityResult(int requestCode, int resultCode, Intent intent),回调函数中可根据 resultCode 参数判断处理情况,根据不同的结果对intent 中的返回值 bundler 对象进行不同处理。 最后使用 callbackContext 对象中的 success(string) 方法把处理结果回传到页面;
处理结果:
本章小结
Cordova(PhoneGap) 技术使用了CordovaPlugin 插件化(模块化)技术,使用不同插件对不同HTML5页面进行分别处理。与此同时,系统也可以利用插件调用系统已有的地图、通信录、浏览器等多个API, 与 HTML5 页面进行信息交换,真正实现HTML5与Android、iOS系统的无缝对接。
参考文章
Cordova(PhoneGap)通过CordovaPlugin插件调用 Activity 实例
最新版Cordova 5.1.1(PhoneGap)搭建开发环境
Windows Server 2008 R2 负载平衡入门篇
作者:风尘浪子
http://www.cnblogs.com/leslies2/p/cordovaPlugin.html
原创作品,转载时请注明作者及出处