一 安装node.js
下载地址:
https://nodejs.org/en/
安装完成后,cmd执行
npm install -g cordova
,全局安装Cordova。
注意:可能会有点慢,请耐心等待!
二 cmd创建Android项目
-
1.新建一个项目:
路径名>cordova create 文件名 包名 工程名
-
2.添加Android平台:
cordova platform add android
三 导入工程 运行一下
-
1.导入工程
-
2.运行一下,如果出现以下界面,恭喜你,Cordova环境集成成功,你可以开始下一步操作了。
四 调用插件
-
1.cmd添加摄像机插件:
android路径名>cordova plugin add cordova-plugin-camera
-
2.查看已安装的插件列表
备注:懒得进行以上步骤的朋友,可以点击以下链接直接下载,对于开发使用没有影响。 -
3.编写index.html文件
在head里加入:
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<script type="text/javascript" charset="utf-8" src="cordova.js"></script>
<script type="text/javascript" charset="utf-8">
var destinationType;
document.addEventListener("deviceready",onDeviceReady,false);
//Cordova加载完成会触发
function onDeviceReady() {
destinationType=navigator.camera.DestinationType;
}
//拍照
function capturePhoto() {
if(!navigator.camera){
alert('camera:')
}
//拍照并获取Base64编码的图像(quality : 存储图像的质量,范围是[0,100])
navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 50,
destinationType: destinationType.DATA_URL }
);
}
//拍照成功
function onPhotoDataSuccess(imageData) {
console.log(imageData);
var smallImage = document.getElementById('smallImage');
smallImage.style.display = 'block';
smallImage.src = "data:image/jpeg;base64," + imageData;
}
//拍照失败
function onFail(message) {
alert('拍照失败: ' + message);
}
</script>
</head>
在body里加入:
<body style="padding-top:50px">
<button style="font-size:23px;" onclick="capturePhoto();">拍摄照片</button> <br>
<img style="display:none;width:240px;height:320px;" id="smallImage" src="" />
</body>
- 4.调用相机插件:
1.将CordovaLib作为Library引入到项目中;
2.把示例demo中的src目录下的org文件夹、assets文件夹下内容、res文件夹下xml文件夹下的config.xml、AndroidManifest.xml中权限服务考到自己项目中。
3.写代码:
(1).创建一个activity extends CordovaActivity;
(2).loadUrl(“file:///android_asset/www/index.html”);
(3).将步骤3写好的index.html考到assets/www/目录下;
(4).运行到手机上,应该据可以调用摄像头功能了。
添加插件一览:
1.
Device
(设备)获取一些设备信息。
cordova plugin add cordova-plugin-device
2.
Connection
(网络连接)用来判断网络连接类型(2G、3G、4G、Wifi、无连接等)。
cordova plugin add cordova-plugin-network-information
3.
Battery
(电池)可以获取电池状态信息。
cordova plugin add cordova-plugin-battery-status
4.
Accelerometer
(加速计)让应用在三维空间(使用笛卡尔三维坐标系统)中决定设备方向。
cordova plugin add cordova-plugin-device-motion
5.
Compass
(指南针)可以让开发者读取移动设备的朝向。
cordova plugin add cordova-plugin-device-orientation
6.
Geolocation
(地理定位)让应用判断设备的物理位置。
cordova plugin add cordova-plugin-geolocation
7.
Camera
(相机)用相机获取图像。
cordova plugin add cordova-plugin-camera
8.
MediaCapture
(媒体捕获)与Camera API相比,不仅能获取图像,还可以录视频或者录音。
cordova plugin add cordova-plugin-media-capture
9.
Media
(播放/记录媒体文件)让应用能记录或播放媒体文件。用它可以在手机后台播放音频文件或玩桌面视频游戏。
cordova plugin add cordova-plugin-media
10.
file
(文件访问操作类)提供对设备上的文件进行读取和写入的功能支持。
cordova plugin add cordova-plugin-file
11.
fileTransfer
(文件传输)实现文件上传、下载及共享等功能。
cordova plugin add cordova-plugin-file-transfer
12.
VisualNotification
(可视化消息提醒)不同于js的alert()、confirm()和prompt()方法是同步的。Cordova的alert()、confirm()和prompt()方法是异步的,并且对显示内容有更大的控制权限。
cordova plugin add cordova-plugin-dialogs
13.
HardwareNofifications
(硬件消息提醒)让设备蜂鸣或振动。
cordova plugin add cordova-plugin-vibration
14.
Contacts
(联系人)读取联系人列表并在应用中使用联系人数据,或使用应用数据向联系人列表中写新的联系人。
cordova plugin add cordova-plugin-contacts
15.
Globalization
(全球化)允许应用查询操作系统的当前设置,判断用户使用的语言。
cordova plugin add cordova-plugin-globalization
16.
Splashscreen
(闪屏)用来在Cordova应用启动时显示自定义的闪屏。
cordova plugin add cordova-plugin-splashscreen
17.
InAppBrowser
(内置浏览器)允许在在单独的窗口中加载网页。例如要向应用用户展示其他网页。当然可以很容易地在应用中加载网页内容并管理,但有时候需要不同的用户体验,InAppBrowser加载网页内容,应用用户可以更方便的直接返回到主应用。
cordova plugin add cordova-plugin-inappbrowser
18.
Console
(调试控制台)让程序可以在控制台中打印输出日志。
cordova plugin add cordova-plugin-console
19.
exitApp
(退出应用)让 Android 或者 Windows Phone 8 上的APP关闭退出(iOS系统不支持)
cordova plugin add cordova-plugin-exitapp
20.
barcodeScanner
(条形码/二维码扫描)不仅可以通过摄像头识别二维码/条形码,还能生成二维码。
cordova plugin add cordova-plugin-barcodescanner
命令一览:
1.查看所有已经安装的插件
cordova plugin ls
2.安装插件(以camera插件为例)
cordova plugin add cordova-plugin-camera
3.删除插件(以camera插件为例)
cordova plugin rm cordova-plugin-camera
4.更新插件
cordova plugin update
五 Android studio环境下将CordovaLib作为依赖导入
环境:Android Studio 2.2
– 1.将CordovaLib作为module导入
– 2.添加依赖
六 自定义插件
- 1.自定义你的java类
1.1.包名,等下会用到。
1.2.集成的父类。
1.3.重写的方法。
1.4.传递的参数。
1.5.action匹配。
- 2.在config.xml文件中添加配置
2.1.js文件名
2.2.java类路径名(详见1.1)
- 3.在assets/www/plugins文件夹下新建文件夹cordova-plugin-xxxx文件夹,并在此文件夹下新建xxxx.js文件。
3.1.js的文件夹名.文件名
3.2.方法名
3.3.与config.xml文件下一致
3.4.方法名==2(与java文件下action一致)
3.5.成功回调函数
3.6.失败回调函数 [content,type]是传递的参数
- 4.在cordova_plugins.js中添加必要配置
4.1.file:js路径名
4.2.id:js的文件夹名.文件名
4.3.html文件中方法名的前缀 在module.exports.metadata中添加
4.5. js的文件夹名
4.6.版本号
- 5.在index.html中调用
function Toast(){
navigator.Toast.getTost("Toast测试",0,onSuccess,onError);
function onSuccess(Data){
alert(JSON.stringify(Data));
}
function onError(Data){
alert(JSON.stringify(Data));
}
}
七 java类中的一些问题
-
1.startActivityForResult
查看CordovaActivty源码:
查看CordovaPlugin源码:
在webView的CordovaActivity获取到Result后,会调用cordovaInterface.onActivityResult(requestCode, resultCode, intent)方法通知CordovaPlugin。如果使用cordova.getActivity().startActivityForResult(intent,CORDOVA_SPEEN)方式,并没有将CordovaPlugin传进去,在webView的CordovaActivity获取到Result后,结果只会返回到的webView的CordovaActivity当中,并不会进行下一步。 -
2.回调
mCallbackContext.success(JSONObject);
mCallbackContext.error(JSONObject);
八 在CordovaActivity中添加原生View组件 #
原因:继承CordovaActivity的子类中默认只有一个WebView,实际开发中不能满足需求。
解决方案:可以使用setContentView设置XML布局,需要重写的两种方法:makewebview 和createviews。(亲测通过extends Activity implements CordovaInterface方法实现时,cordova.startActivityForResult不回调,具体原因尚不明)
–
makewebview() :
很重要,它使用R.id.cordovawebview,会定义在XML布局文件。
–
createViews() :
它会默认使用setContentView,想使用自己定义的布局,需要重写该方法。
实现功能:在WebView上增加TitleBar。
– 1.布局文件(R.layout.activity_cordova_title)
<?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:orientation="vertical" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="45dip"
android:background="#25C28B" >
<ImageButton
android:id="@+id/cordova_back"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#00FFFFFF"
android:paddingLeft="10dp"
android:paddingRight="20dp"
android:src="@drawable/back" />
<TextView
android:id="@+id/cordova_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="原生头部"
android:textColor="#FFFFFF"
android:textSize="20sp" />
<Button
android:id="@+id/cordova_close"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:background="#00FFFFFF"
android:paddingLeft="10dp"
android:paddingRight="20dp"
android:text="关闭"
android:textColor="#FFFFFF"
android:textSize="20sp" />
</RelativeLayout>
<org.apache.cordova.engine.SystemWebView
android:id="@+id/cordovaWebView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
- 2.自定义CordovaActivity类(CordovaTitleActivity)
参照源码copy过来的,因为要使用自定义布局,所以setContentView相关代码注掉
public class CordovaTitleActivity extends CordovaActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cordova_title);
loadUrl(launchUrl);
}
@Override
protected CordovaWebView makeWebView() {
SystemWebView webView = (SystemWebView) findViewByI(R.id.cordov_webView);
CordovaWebView cordovaWebView = new CordovaWebViewImpl(new SystemWebViewEngine(webView));
return cordovaWebView;
}
@Override
protected void createViews() {
//因为要使用自定义布局,此处setContentView需要注掉
// appView.getView().setId(100);
// appView.getView().setLayoutParams(new FrameLayout.LayoutParams(
// ViewGroup.LayoutParams.MATCH_PARENT,
// ViewGroup.LayoutParams.MATCH_PARENT));
// setContentView(appView.getView());
if (preferences.contains("BackgroundColor")) {
int backgroundColor = preferences.getInteger("BackgroundColor", Color.BLACK);
// Background of activity:
appView.getView().setBackgroundColor(backgroundColor);
}
appView.getView().requestFocusFromTouch();
}
}
- 3.使用Cordova需要注意的问题
1. 在Activity的onCreate方法中,loadUrl(launchUrl)调用之后,CordovaLib中的WebView对象appView才有值,因此使用appView时,必须写在loadUrl的后面。
2. 在Cordova中,appView是不能直接调用addJavascriptInterface()方法的,在调用该方法之前,需要加上一行代码:
WebView Wv = (WebView) appView.getEngine().getView();
调用WebView的其他方法类似。
九 在Fragment里使用CordovaWebView
- 1.Fragment的布局文件(cordova_fragmrnt.xml)
<?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:orientation="vertical" >
<org.apache.cordova.engine.SystemWebView
android:id="@+id/cordov_webView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
-2.Fragment
public class MyFragmentNew extends BaseFragment implements CordovaInterface {
public static MyFragmentNew newInstance() {
MyFragmentNew fragment = new MyFragmentNew();
return fragment;
}
private String TAG = "MyFragmentNew";
private CordovaWebView myCordovaWebView;
private Context mContext;
// Plugin to call when activity result is received
protected CordovaPlugin activityResultCallback = null;
protected boolean activityResultKeepRunning;
// Keep app running when pause is received. (default = true)
// If true, then the JavaScript and native code continue to run in the
// background
// when another application (activity) is started.
protected boolean keepRunning = true;
private final ExecutorService threadPool = Executors.newCachedThreadPool();
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mContext = inflater.getContext();
View thisView = inflater.inflate(R.layout.home_pager_fragment_new,
container, false);
SystemWebView homeWebView = (SystemWebView) thisView
.findViewById(R.id.cordov_webView_home);
ConfigXmlParser parser = new ConfigXmlParser();
parser.parse(getActivity());// 这里会解析res/xml/config.xml配置文件
myCordovaWebView = new CordovaWebViewImpl(new SystemWebViewEngine(
homeWebView));// 创建一个cordovawebview
myCordovaWebView.init(new CordovaInterfaceImpl(getActivity()),
parser.getPluginEntries(), parser.getPreferences());// 初始化
myCordovaWebView.loadUrl("file:///android_asset/www/index.html");// 加载网页
return thisView;
}
@Override
public void startActivityForResult(CordovaPlugin command, Intent intent,
int requestCode) {
this.activityResultCallback = command;
this.activityResultKeepRunning = this.keepRunning;
// If multitasking turned on, then disable it for activities that return
if (command != null) {
this.keepRunning = false;
}
// Start activity
super.startActivityForResult(intent, requestCode);
}
@Override
public void setActivityResultCallback(CordovaPlugin plugin) {
this.activityResultCallback = plugin;
}
@Override
public void onDestroy() {
super.onDestroy();
if (myCordovaWebView != null) {
myCordovaWebView.handleDestroy();
}
}
@Override
public Object onMessage(String id, Object data) {
return null;
}
@Override
public ExecutorService getThreadPool() {
return threadPool;
}
@Override
public void requestPermission(CordovaPlugin plugin, int requestCode,
String permission) {
// TODO Auto-generated method stub
}
@Override
public void requestPermissions(CordovaPlugin plugin, int requestCode,
String[] permissions) {
// TODO Auto-generated method stub
}
@Override
public boolean hasPermission(String permission) {
// TODO Auto-generated method stub
return false;
}
}
- 3.需要在Fragment所在的Activity中重写onActivityResult()方法,将结果通知给自定义插件
public static CordovaPlugin mCordovaPlugin;
/**
* 为了将回调结果回传给Cordova插件
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
CordovaPlugin cordovaPlugin = this.mCordovaPlugin;
if(cordovaPlugin != null){
cordovaPlugin.onActivityResult(requestCode,resultCode,data);
}
super.onActivityResult(requestCode, resultCode, data);
}
- 4.在自定义插件类里给步骤3里的mCordovaPlugin赋值
public boolean execute(String action, JSONArray args,
CallbackContext callbackContext) throws JSONException {
// TODO Auto-generated method stub
mCallbackContext = callbackContext;
/*给fragment所在activity里的mCordovaPlugin赋值,否则fragment所在activity里onActivityResult()
* 无法将结果传给插件的onActivityResult()。*/
MyFragmentActivity.mCordovaPlugin = (CordovaPlugin) this;
// 语音识别
if ("getSpeechData".equals(action)) {
RequestData = args.getJSONObject(0);
Intent intent = new Intent(cordova.getActivity(),
SpeechActivity.class);
intent.putExtra("flag", RequestData.getInt("flag"));
this.cordova.startActivityForResult((CordovaPlugin) this, intent,
CORDOVA_SPEEN);
return true;
}
十 Fragment拦截返回键
-
1.原理:利用Fragment的生命周期,在Fragment显示时通知到Activity,并由Activity保持。当用户按下物理返回键时,首先将back键请求交给Fragment处理,如果处理返回true,未处理时返回false。如果Fragment没有处理则由Activity处理。为保证Fragment存在嵌套的情况下也能正常使用,可以使用FragmentManager去管理持有的子Fragment,FragmentManager使用递归方式处理。
-
2.定义FragmentBackHandler接口
public interface FragmentBackHandler {
//用于判断子fragment是否对返回键做处理
boolean onGoBack();
}
- 3.定义一个BackHandlerHelper工具类,用于实现分发back事件,Fragment和Activity的外理逻辑是一样,所以两者都需要调用该类的方法。
public class BackHandlerHelper {
/**
* 将back事件分发给 FragmentManager 中管理的子Fragment,如果该 FragmentManager
* 中的所有Fragment都 没有处理back事件,则尝试 FragmentManager.popBackStack()
*
* @param fragmentManager
* @return
*/
public static boolean handleBackPress(FragmentManager fragmentManager) {
List<Fragment> fragments = fragmentManager.getFragments();
if (fragments == null)
return false;
for (int i = fragments.size() - 1; i >= 0; i--) {
Fragment child = fragments.get(i);
if (isFragmentBackHandled(child)) {
return true;
}
}
if (fragmentManager.getBackStackEntryCount() > 0) {
fragmentManager.popBackStack();
return true;
}
return false;
}
public static boolean handleBackPress(Fragment fragment) {
return handleBackPress(fragment.getChildFragmentManager());
}
public static boolean handleBackPress(FragmentActivity fragmentActivity) {
return handleBackPress(fragmentActivity.getSupportFragmentManager());
}
public static boolean isFragmentBackHandled(Fragment fragment) {
return fragment != null
&& fragment.isVisible()
&& fragment.getUserVisibleHint() // for ViewPager
&& fragment instanceof FragmentBackHandler
&& ((FragmentBackHandler) fragment).onGoBack();
}
}
- 3.在Fragment里实现FragmentBackHandler接口
public class MyFragmentNew extends BaseFragment implements FragmentBackHandler{
@Override
public boolean onGoBack() {
if(myCordovaWebView.canGoBack()){
myCordovaWebView.getEngine().goBack();
return true;
}
//return BackHandlerHelper.handleBackPress(this);
//当确认没有子Fragmnt时可以直接return false
return false;
}
}
- 4.在宿主Activity覆盖onBackPressed方法
public class MyActivity extends FragmentActivity {
//.....
@Override
public void onBackPressed() {
//子Fragment没有做拦截处理
if (!BackHandlerHelper.handleBackPress(this)) {
super.onBackPressed();
}
}
}