cordova也叫phonegap,可以用来打包网页生成Android或iOS或其他平台的APP,它提供了一些native api,可以让网页调用本地函数,极大地增强了网页的功能。
cordova的使用非常灵活,可以全部用网页和js来实现APP功能,也可以使用网页+本地代码的形式来实现。
cordova 的官方网站是http://cordova.apache.org,目前看来它的文档有些落后代码,一切以代码为准。
目录
1.工作环境建立
创建工程
生成APP
使用CordovaWebView
js调用本地代码
本地代码调用js
1.工作环境建立:
sudo apt-get install nodejs
sudo apt-get install nodejs-legacy
sudo apt-get install npm
sudo npm install -g cordova
cordova platform add android
创建工程
cordova create dir_name package_name app_name
例如:
cordova create hello com.example.hello HelloWorld
会创建hello目录,在此目录中创建工程,com.example.hello这个是工程的包名,HelloWorld是应用的显示名字。
hello目录结构如下:
├── config.xml
├── hooks
│ └── README.md
├── platforms
├── plugins
└── www
├── css
│ └── index.css
├── img
│ └── logo.png
├── index.html
└── js
└── index.js
生成APP
cd hello
cordova build
此时会在platforms目录下生成android目录,这个就是android平台的APP工程目录。
├── AndroidManifest.xml
├── assets //所有的网页和js等文件放到此目录
├── build
├── build.gradle
├── cordova
├── CordovaLib
├── gradle
├── gradlew
├── libs
├── platform_www
├── project.properties
├── res //此目录下有一个xml/config.xml,这是cordova的全局配置
├── settings.gradle
└── src
<org.apache.cordova.engine.SystemWebView
android:id="@+id/home_fragment_webview"
android:layout_marginTop="@dimen/home_fragment_web_view_margin_top"
android:layout_marginBottom="@dimen/home_fragment_web_view_margin_bottom"
android:layout_below="@id/home_fragment_card_clock"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
这个时候build/outputs/apk/目录下已经创建了APK文件。
使用CordovaWebView
首先看了网上的资料,以为这是一个View,官网上也是这样写的:
SystemWebView继承了WebView
在代码中:
ConfigXmlParser parser=new ConfigXmlParser();
parser.parse(activity);//这里会解析res/xml/config.xml配置文件
CordovaWebView cordovaWebView= new CordovaWebViewImpl(new SystemWebViewEngine(systemWebView));//创建一个cordovawebview
cordovaWebView.init(new MyCordovaInterfaceImpl(activity), parser.getPluginEntries(), parser.getPreferences());//初始化
cordovaWebView.loadUrl(“file:///android_asset/www/index.html“);//加载网页
private static class MyCordovaInterfaceImpl extends CordovaInterfaceImpl{
private Activity mActivity;
public MyCordovaInterfaceImpl(Activity activity) {
super(activity);
mActivity=activity;
}
@Override
public Activity getActivity() {
return mActivity; //注意这里要返回activity
}
}
因为cordova默认不加载外部网页,需要自己定义一个插件plugin才能加载外部网页,否则会报错,自定义插件如下:
public class MyCordovaPlugin extends CordovaPlugin {
@Override
public Boolean shouldAllowNavigation(String url) {
return true;
}
@Override
public Boolean shouldAllowRequest(String url) {
return true;
}
}
在xml/config.xml中定义全局插件:
<feature name="myplugin">
<param name="android-package" value="com.example.MyCordovaPlugin"/>
<param name="onload" value="true"/>
</feature>
然后在代码中就可以自由加载外部网页了:
cordovaWebView.loadUrl(“http://www.baidu.com/“);//加载外部网页
JS调用本地代码
在plugin中重写execute
@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
if(action.equals("message")){//响应action请求
//SingleToast.showShort(MainApplication.getInstance(),args.getString(0));
callbackContext.success("hahahaha"); //返回结果
return true; //一定要返回true,返回false表示invalid action
}
return false;
}
在js中可以直接调用,调用方法如下:
function message(){
cordova.exec(onMessageSuccess,onMessageError,"myplugin","message",["hello wrold"]);
}
function onMessageSuccess(result){
alert("成功啦:> "+result);
}
function onMessageError(result){
alert("失败了:( "+result);
}
exec函数定义如下:
exec(<successFunction>, <failFunction>, <service>, <action>, [<args>]);
本地代码调用JS
本地代码调用JS稍微复杂一点,原先可以用sendJavascript,但是现在已经被标记过时了,所以还是不要用为好,目前的方法如下:
在js中注册一个通道,并向本地代码发送一个oncalljs消息
cordova.require('cordova/channel').onCordovaReady.subscribe(function() {
cordova.exec(oncalljs, null, “myplugin”, “oncalljs”, []);
function oncalljs(message) {
//在这里响应来自本地代码的调用
if(message==”1”){
//...
}
}
});
然后在本地代码的exec函数中响应oncalljs,并保存调用上下文:
if(action.equals("oncalljs")){
mCallbackContext=callbackContext;
PluginResult dataResult = new PluginResult(PluginResult.Status.OK,"js call init ok");
dataResult.setKeepCallback(true);//非常重要
mCallbackContext.sendPluginResult(dataResult);
return true; //非常重要
}
之后,本地代码就可以调用JS了:
public void sendCmd(String cmd){
if(mCallbackContext!=null){
PluginResult dataResult = new PluginResult(PluginResult.Status.OK,cmd);
dataResult.setKeepCallback(true);//非常重要
mCallbackContext.sendPluginResult(dataResult);
}
}