在開發(fā)的過程中我們更多的是使用別人開發(fā)的cordova插件,但是在使用的過程中經(jīng)常會遇到一些不合自己心意的問題,那么我們就來使用plugman開發(fā)一個屬于自己的cordova插件吧。
源碼地址 : https://github.com/DaiHuaXieHuaKai/GaoDeLocation.git
下面就以開發(fā)一個高德地圖的定位插件為例:
第一步:檢查是否具備開發(fā)環(huán)境
檢查是否有cordova和plugman的環(huán)境
分別執(zhí)行cordova -v和plugman -v查看是否有版本號出現(xiàn),如果沒有安裝這兩個環(huán)境請按照以下步驟安裝:
安裝crodva和plugman都需要使用nodejs的npm管理工具,所以我們先要安裝nodejs,nodejs下載地址,下載安裝后執(zhí)行npm -v出現(xiàn)版本號即安裝成功。
安裝cordova:
npm install -g cordova
安裝plugman:
npm install -g plugman
然后分別執(zhí)行cordova -v和plugman -v檢查是否環(huán)境搭建成功。
第二步:使用plugman創(chuàng)建插件模板
//創(chuàng)建插件 (GaoDeLocation為插件名稱, com.zhaoying.GaoDeLocation為插件id
plugman create --name GaoDeLocation --plugin_id com.zhaoying.GaoDeLocation--plugin_version 1.0.0
//進(jìn)入GaoDeLocation 目錄
cd GaoDeLocation
//為插件添加android平臺(此處只添加了安卓,如果要開發(fā)ios插件請執(zhí)行plugman platform add --platform_name ios)
plugman platform add --platform_name android
模板創(chuàng)建成功后目錄格式如下:
第三步:修改配置模板
| 元素 | 描述 |
|---|---|
| id | 插件id,創(chuàng)建插件的時候設(shè)定,該id可用于添加插件,如:cordova plugin add com.zhaoying.GaoDeLocation |
| name | 插件名稱 |
| js-module | 這里指定clobbers ,然后通過它來調(diào)用GaoDeLocation.js,此處應(yīng)該對應(yīng)GaoDeLocation.js中exports的對象 |
| preference | 指定參數(shù),比如這里設(shè)定了API_KEY這個參數(shù),在添加插件的時候就必須加上--variable API_KEY=your key |
| config-file | 這里主要是填寫一些配置信息,比如高德定位的獲取定位權(quán)限等等 |
| source-file | 用于指定引用的libs的資源和路徑 |
1、修改plugin.xml
plugin.xml的配置非常重要,以下是幾個重要的地方:
| 元素 | 描述 |
|---|---|
| id | 插件id,創(chuàng)建插件的時候設(shè)定,該id可用于添加插件,如:cordova plugin add com.zhaoying.GaoDeLocation |
| name | 插件名稱 |
| js-module | 這里指定clobbers ,然后通過它來調(diào)用GaoDeLocation.js,此處應(yīng)該對應(yīng)GaoDeLocation.js中exports的對象 |
| preference | 指定參數(shù),比如這里設(shè)定了API_KEY這個參數(shù),在添加插件的時候就必須加上--variable API_KEY=your key |
| config-file | 這里主要是填寫一些配置信息,比如高德定位的獲取定位權(quán)限等等 |
| source-file | 用于指定引用的libs的資源和路徑 |
我們修改后的plugin.xml如下:
<?xml version='1.0' encoding='utf-8'?>
<plugin id="com.zhaoying.GaoDeLocation" version="1.0.0" xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android">
<name>GaoDeLocation</name>
<js-module name="GaoDe" src="www/GaoDeLocation.js">
<clobbers target="GaoDe"/>
</js-module>
<preference name="API_KEY" />
<platform name="android">
<config-file parent="/*" target="res/xml/config.xml">
<feature name="GaoDeLocation">
<param name="android-package" value="com.zhaoying.GaoDeLocation.GaoDeLocation"/>
</feature>
</config-file>
<!--以下配置完全按照高德的指南進(jìn)行配置,詳見:http://lbs.amap.com/api/android-location-sdk/gettingstarted/-->
<config-file target="AndroidManifest.xml" parent="/manifest/application">
<!--在AndroidManifest.xml的application標(biāo)簽中配置Key:-->
<meta-data android:name="com.amap.api.v2.apikey" android:value="$API_KEY">
</meta-data>
<!--在application標(biāo)簽中聲明service組件:-->
<service android:name="com.amap.api.location.APSService"></service>
</config-file>
<config-file parent="/*" target="AndroidManifest.xml">
<!--用于進(jìn)行網(wǎng)絡(luò)定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
<!--用于訪問GPS定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
<!--獲取運(yùn)營商信息,用于支持提供運(yùn)營商信息相關(guān)的接口-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<!--用于訪問wifi網(wǎng)絡(luò)信息,wifi信息會用于進(jìn)行網(wǎng)絡(luò)定位-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<!--這個權(quán)限用于獲取wifi的獲取權(quán)限,wifi信息會用來進(jìn)行網(wǎng)絡(luò)定位-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
<!--用于訪問網(wǎng)絡(luò),網(wǎng)絡(luò)定位需要上網(wǎng)-->
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<!--用于讀取手機(jī)當(dāng)前的狀態(tài)-->
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
<!--寫入擴(kuò)展存儲,向擴(kuò)展卡寫入數(shù)據(jù),用于寫入緩存定位數(shù)據(jù)-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<!--用于申請調(diào)用A-GPS模塊-->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"></uses-permission>
<!--用于申請獲取藍(lán)牙信息進(jìn)行室內(nèi)定位-->
<uses-permission android:name="android.permission.BLUETOOTH"></uses-permission>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"></uses-permission>
</config-file>
<source-file src="src/android/GaoDeLocation.java" target-dir="src/com/zhaoying/GaoDeLocation"/>
<source-file src="libs/android/AMap_Location_V3.3.0.jar" target-dir="libs" />
</platform>
</plugin>
此處我們要注意需要將:
<source-file src="src/android/GaoDeLocation.java" target-dir="src/com/zhaoying/GaoDeLocation/GaoDeLocation"/>
修改為:
<source-file src="src/android/GaoDeLocation.java" target-dir="src/com/zhaoying/GaoDeLocation"/>
如果不修改的話會找不到GaoDeLocation.js.
第四步:添加高德SDK,修改GaoDeLocation.js
首先在http://lbs.amap.com/api/android-location-sdk/download/下載需要用到的jar包,這里我們只需要下載定位的jar即可。
下載完成后將其解壓,并將jar包引入插件項(xiàng)目,這里需要我們在插件項(xiàng)目中創(chuàng)建一個libs文件夾來放jar包,最終結(jié)構(gòu)如下:
然后我們先要修改GaoDeLocation.js文件,將其修改為:
var exec = require('cordova/exec');
var GaoDe = {
getCurrentPosition:function (successFn,errorFn) {
exec(successFn,errorFn,'GaoDeLocation','getCurrentPosition',[]);
}
};
module.exports = GaoDe;
然后我們需要修改GaoDeLocation.java文件,修改為:(具體的方法可以參照官方demo進(jìn)行添加或修改)
package com.zhaoying.GaoDeLocation;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationClientOption.AMapLocationMode;
import com.amap.api.location.AMapLocationClientOption.AMapLocationProtocol;
import com.amap.api.location.AMapLocationListener;
/**
* @author zhaoying
*/
public class GaoDeLocation extends CordovaPlugin {
//聲明AMapLocationClient類對象
public AMapLocationClient locationClient = null;
//聲明定位參數(shù)
public AMapLocationClientOption locationOption = null;
/**
* JS回調(diào)接口對象
*/
public static CallbackContext cb = null;
/*
* 程序入口
* */
@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
if (action.equals("getCurrentPosition")) {
cb = callbackContext;
PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
pluginResult.setKeepCallback(true);
cb.sendPluginResult(pluginResult);
this.getCurrentPosition();
return true;
}
return false;
}
/**
* 獲取定位
*
* @author zhaoying
*/
private void getCurrentPosition() {
if (locationClient == null) {
this.initLocation();
}
this.startLocation();
}
/**
* 初始化定位
*
* @author zhaoying
*/
private void initLocation() {
//初始化client
locationClient = new AMapLocationClient(this.webView.getContext());
//設(shè)置定位參數(shù)
locationClient.setLocationOption(getDefaultOption());
// 設(shè)置定位監(jiān)聽
locationClient.setLocationListener(locationListener);
}
/**
* 默認(rèn)的定位參數(shù)
*
* @author zhaoying
*/
private AMapLocationClientOption getDefaultOption() {
AMapLocationClientOption mOption = new AMapLocationClientOption();
mOption.setLocationMode(AMapLocationMode.Hight_Accuracy);//可選,設(shè)置定位模式,可選的模式有高精度、僅設(shè)備、僅網(wǎng)絡(luò)。默認(rèn)為高精度模式
mOption.setGpsFirst(false);//可選,設(shè)置是否gps優(yōu)先,只在高精度模式下有效。默認(rèn)關(guān)閉
mOption.setHttpTimeOut(30000);//可選,設(shè)置網(wǎng)絡(luò)請求超時時間。默認(rèn)為30秒。在僅設(shè)備模式下無效
mOption.setInterval(2000);//可選,設(shè)置定位間隔。默認(rèn)為2秒
mOption.setNeedAddress(true);//可選,設(shè)置是否返回逆地理地址信息。默認(rèn)是true
mOption.setOnceLocation(false);//可選,設(shè)置是否單次定位。默認(rèn)是false
mOption.setOnceLocationLatest(false);//可選,設(shè)置是否等待wifi刷新,默認(rèn)為false.如果設(shè)置為true,會自動變?yōu)閱未味ㄎ?,持續(xù)定位時不要使用
AMapLocationClientOption.setLocationProtocol(AMapLocationProtocol.HTTP);//可選, 設(shè)置網(wǎng)絡(luò)請求的協(xié)議??蛇xHTTP或者HTTPS。默認(rèn)為HTTP
mOption.setSensorEnable(false);//可選,設(shè)置是否使用傳感器。默認(rèn)是false
mOption.setWifiScan(true); //可選,設(shè)置是否開啟wifi掃描。默認(rèn)為true,如果設(shè)置為false會同時停止主動刷新,停止以后完全依賴于系統(tǒng)刷新,定位位置可能存在誤差
mOption.setLocationCacheEnable(true); //可選,設(shè)置是否使用緩存定位,默認(rèn)為true
return mOption;
}
/**
* 定位監(jiān)聽
*/
AMapLocationListener locationListener = new AMapLocationListener() {
@Override
public void onLocationChanged(AMapLocation location) {
try {
JSONObject json = new JSONObject();
if (null != location) {
//解析定位結(jié)果
//errCode等于0代表定位成功,其他的為定位失敗,具體的可以參照官網(wǎng)定位錯誤碼說明
if (location.getErrorCode() == 0) {
json.put("status", "定位成功");
//定位類型
json.put("type", location.getLocationType());
//緯度
json.put("latitude", location.getLatitude());
//經(jīng)度
json.put("longitude", location.getLongitude());
//精度
json.put("accuracy", location.getAccuracy());
//角度
json.put("bearing", location.getBearing());
// 獲取當(dāng)前提供定位服務(wù)的衛(wèi)星個數(shù)
//星數(shù)
json.put("satellites", location.getSatellites());
//國家
json.put("country", location.getCountry());
//省
json.put("province", location.getProvince());
//市
json.put("city", location.getCity());
//城市編碼
json.put("citycode", location.getCityCode());
//區(qū)
json.put("district", location.getDistrict());
//區(qū)域碼
json.put("adcode", location.getAdCode());
//地址
json.put("address", location.getAddress());
//興趣點(diǎn)
json.put("poi", location.getPoiName());
//興趣點(diǎn)
json.put("time", location.getTime());
} else {
json.put("status", "定位失敗");
json.put("errcode", location.getErrorCode());
json.put("errinfo", location.getErrorInfo());
json.put("detail", location.getLocationDetail());
}
//定位之后的回調(diào)時間
json.put("backtime",System.currentTimeMillis());
} else {
}
PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, json);
pluginResult.setKeepCallback(true);
cb.sendPluginResult(pluginResult);
} catch (JSONException e) {
PluginResult pluginResult = new PluginResult(PluginResult.Status.ERROR, e.getMessage());
pluginResult.setKeepCallback(true);
cb.sendPluginResult(pluginResult);
} finally {
locationClient.stopLocation();
}
}
};
/**
* 開始定位
*
* @author zhaoying
*/
private void startLocation() {
// 啟動定位
locationClient.startLocation();
}
/**
* 停止定位
*
* @author zhaoying
*/
private void stopLocation() {
// 停止定位
locationClient.stopLocation();
}
/**
* 銷毀定位
*
* @author zhaoying
*/
private void destroyLocation() {
if (null != locationClient) {
/**
* 如果AMapLocationClient是在當(dāng)前Activity實(shí)例化的,
* 在Activity的onDestroy中一定要執(zhí)行AMapLocationClient的onDestroy
*/
locationClient.onDestroy();
locationClient = null;
locationOption = null;
}
}
}
第五步:添加插件,調(diào)用定位
首先新建一個ionic項(xiàng)目(具體方法參照ionic官網(wǎng)文檔)
項(xiàng)目新建完成后,添加剛剛新建完成的插件:
cordova plugin add C:\Users\HD\GaoDeLocation --variable API_KEY=yourkey
這里需要用到API_KEY,該key需要在高德地圖的控制臺去申請,具體參照
添加完成后就可以在頁面中調(diào)用定位方法了:
GaoDe.getCurrentPosition(function (success) {
console.log(success);
},function (error) {
console.log(error)
})