1. 程式人生 > >使用plugman開發cordova 高德地圖定位外掛

使用plugman開發cordova 高德地圖定位外掛

在開發的過程中我們更多的是使用別人開發的cordova外掛,但是在使用的過程中經常會遇到一些不合自己心意的問題,那麼我們就來使用plugman開發一個屬於自己的cordova外掛吧。
原始碼地址 : https://github.com/DaiHuaXieHuaKai/GaoDeLocation.git
下面就以開發一個高德地圖的定位外掛為例:

第一步:檢查是否具備開發環境

檢查是否有cordova和plugman的環境
分別執行cordova -v和plugman -v檢視是否有版本號出現,如果沒有安裝這兩個環境請按照以下步驟安裝:
安裝crodva和plugman都需要使用nodejs的npm管理工具,所以我們先要安裝nodejs,

nodejs下載地址,下載安裝後執行npm -v出現版本號即安裝成功。

安裝cordova:
npm install -g cordova
安裝plugman:
npm install -g plugman

然後分別執行cordova -v和plugman -v檢查是否環境搭建成功。

第二步:使用plugman建立外掛模板

//建立外掛 (GaoDeLocation為外掛名稱, com.zhaoying.GaoDeLocation為外掛id
plugman create --name GaoDeLocation --plugin_id com.zhaoying.GaoDeLocation
--plugin_version 1.0.0 //進入GaoDeLocation 目錄 cd GaoDeLocation //為外掛新增android平臺(此處只添加了安卓,如果要開發ios外掛請執行plugman platform add --platform_name ios) plugman platform add --platform_name android

模板建立成功後目錄格式如下:
這裡寫圖片描述

第三步:修改配置模板

1、修改plugin.xml
plugin.xml的配置非常重要,以下是幾個重要的地方:

元素 描述
id 外掛id,建立外掛的時候設定,該id可用於新增外掛,如:cordova plugin add com.zhaoying.GaoDeLocation
name 外掛名稱
js-module 這裡指定clobbers ,然後通過它來呼叫GaoDeLocation.js,此處應該對應GaoDeLocation.js中exports的物件
preference 指定引數,比如這裡設定了API_KEY這個引數,在新增外掛的時候就必須加上–variable API_KEY=your key
config-file 這裡主要是填寫一些配置資訊,比如高德定位的獲取定位許可權等等
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>

        <!--以下配置完全按照高德的指南進行配置,詳見:http://lbs.amap.com/api/android-location-sdk/gettingstarted/-->
        <config-file target="AndroidManifest.xml" parent="/manifest/application">
            <!--在AndroidManifest.xml的application標籤中配置Key:-->
            <meta-data android:name="com.amap.api.v2.apikey" android:value="$API_KEY">
            </meta-data>
            <!--在application標籤中宣告service元件:-->
            <service android:name="com.amap.api.location.APSService"></service>
        </config-file>

        <config-file parent="/*" target="AndroidManifest.xml">
            <!--用於進行網路定位-->
            <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
            <!--用於訪問GPS定位-->
            <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
            <!--獲取運營商資訊,用於支援提供運營商資訊相關的介面-->
            <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
            <!--用於訪問wifi網路資訊,wifi資訊會用於進行網路定位-->
            <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
            <!--這個許可權用於獲取wifi的獲取許可權,wifi資訊會用來進行網路定位-->
            <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
            <!--用於訪問網路,網路定位需要上網-->
            <uses-permission android:name="android.permission.INTERNET"></uses-permission>
            <!--用於讀取手機當前的狀態-->
            <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
            <!--寫入擴充套件儲存,向擴充套件卡寫入資料,用於寫入快取定位資料-->
            <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
            <!--用於申請呼叫A-GPS模組-->
            <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"></uses-permission>
            <!--用於申請獲取藍芽資訊進行室內定位-->
            <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包引入外掛專案,這裡需要我們在外掛專案中建立一個libs資料夾來放jar包,最終結構如下:
這裡寫圖片描述

然後我們先要修改GaoDeLocation.js檔案,將其修改為:

var exec = require('cordova/exec');

var GaoDe = {
    getCurrentPosition:function (successFn,errorFn) {
        exec(successFn,errorFn,'GaoDeLocation','getCurrentPosition',[]);
    }
};

module.exports = GaoDe;

然後我們需要修改GaoDeLocation.java檔案,修改為:(具體的方法可以參照官方demo進行新增或修改)

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;
    //宣告定位引數
    public AMapLocationClientOption locationOption = null;
    /**
     * JS回撥介面物件
     */
    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());
        //設定定位引數
        locationClient.setLocationOption(getDefaultOption());
        // 設定定位監聽
        locationClient.setLocationListener(locationListener);
    }

    /**
     * 預設的定位引數
     *
     * @author zhaoying
     */
    private AMapLocationClientOption getDefaultOption() {
        AMapLocationClientOption mOption = new AMapLocationClientOption();
        mOption.setLocationMode(AMapLocationMode.Hight_Accuracy);//可選,設定定位模式,可選的模式有高精度、僅裝置、僅網路。預設為高精度模式
        mOption.setGpsFirst(false);//可選,設定是否gps優先,只在高精度模式下有效。預設關閉
        mOption.setHttpTimeOut(30000);//可選,設定網路請求超時時間。預設為30秒。在僅裝置模式下無效
        mOption.setInterval(2000);//可選,設定定位間隔。預設為2秒
        mOption.setNeedAddress(true);//可選,設定是否返回逆地理地址資訊。預設是true
        mOption.setOnceLocation(false);//可選,設定是否單次定位。預設是false
        mOption.setOnceLocationLatest(false);//可選,設定是否等待wifi重新整理,預設為false.如果設定為true,會自動變為單次定位,持續定位時不要使用
        AMapLocationClientOption.setLocationProtocol(AMapLocationProtocol.HTTP);//可選, 設定網路請求的協議。可選HTTP或者HTTPS。預設為HTTP
        mOption.setSensorEnable(false);//可選,設定是否使用感測器。預設是false
        mOption.setWifiScan(true); //可選,設定是否開啟wifi掃描。預設為true,如果設定為false會同時停止主動重新整理,停止以後完全依賴於系統重新整理,定位位置可能存在誤差
        mOption.setLocationCacheEnable(true); //可選,設定是否使用快取定位,預設為true
        return mOption;
    }

    /**
     * 定位監聽
     */
    AMapLocationListener locationListener = new AMapLocationListener() {
        @Override
        public void onLocationChanged(AMapLocation location) {
            try {
                JSONObject json = new JSONObject();
                if (null != location) {
                    //解析定位結果
                    //errCode等於0代表定位成功,其他的為定位失敗,具體的可以參照官網定位錯誤碼說明
                    if (location.getErrorCode() == 0) {
                        json.put("status", "定位成功");
                        //定位型別
                        json.put("type", location.getLocationType());
                        //緯度
                        json.put("latitude", location.getLatitude());
                        //經度
                        json.put("longitude", location.getLongitude());
                        //精度
                        json.put("accuracy", location.getAccuracy());
                        //角度
                        json.put("bearing", location.getBearing());
                        // 獲取當前提供定位服務的衛星個數
                        //星數
                        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());
                        //區
                        json.put("district", location.getDistrict());
                        //區域碼
                        json.put("adcode", location.getAdCode());
                        //地址
                        json.put("address", location.getAddress());
                        //興趣點
                        json.put("poi", location.getPoiName());
                        //興趣點
                        json.put("time", location.getTime());
                    } else {
                        json.put("status", "定位失敗");
                        json.put("errcode", location.getErrorCode());
                        json.put("errinfo", location.getErrorInfo());
                        json.put("detail", location.getLocationDetail());
                    }
                    //定位之後的回撥時間
                    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是在當前Activity例項化的,
             * 在Activity的onDestroy中一定要執行AMapLocationClient的onDestroy
             */
            locationClient.onDestroy();
            locationClient = null;
            locationOption = null;
        }
    }

}

第五步:新增外掛,呼叫定位

首先新建一個ionic專案(具體方法參照ionic官網文件)
專案新建完成後,新增剛剛新建完成的外掛:

cordova plugin add C:\Users\HD\GaoDeLocation --variable API_KEY=yourkey

這裡需要用到API_KEY,該key需要在高德地圖的控制檯去申請,具體參照

新增完成後就可以在頁面中呼叫定位方法了:

    GaoDe.getCurrentPosition(function (success) {
      console.log(success);
    },function (error) {
      console.log(error)
    })