前言
- web端的定位是不准确的,在一些对定位要求不高的情况下可以用,比如只需要定位到城市用来查询天气
效果展示

安装插件方式1:命令安装
安装定位插件
cordova plugin add https://github.com/yanxiaojun617/com.kit.cordova.amaplocation --save
安装导航插件.如果只需要定位,则不需要安装导航插件
cordova plugin add https://github.com/yanxiaojun617/com.kit.cordova.amapnavigation --save

安装插件方式2:手动安装
-
下载插件到本地,如下图点击Download Zip
-
解压.zip后.删掉文件夹目录
-master
后缀
3.复制插件文件夹到app项目plugins
目录下.此时插件已经安装完成,可以使用了

4.为了让插件集成的更完善.可以修改fetch.json
和config.xml
声明插件来源


"com.kit.cordova.amaplocation": {
"source": {
"type": "git",
"url": "https://github.com/yanxiaojun617/com.kit.cordova.amaplocation",
"subdir": "."
},
"is_top_level": true,
"variables": {}
}
<plugin name="com.kit.cordova.amaplocation" spec="https://github.com/yanxiaojun617/com.kit.cordova.amaplocation" />
获取key
- 在高德开发平台控制台添加Android和ios key
- Android平台key分debug key 和release key,对应debug Apk和release Apk
- 获取release key需要对app签名获得keystore文件,在开发调试阶段可以先只获取地图debug key,如下图红色字体标注.还需要注意的是,debug key每台电脑都不一样,如果另一位同事也要调试地图定位功能,则需要在他电脑上申请debug key
添加Android平台key
添加ios平台key
配置插件key
-
把申请的Android key填写到如下图位置
-
把申请的ios key填写到如下图位置
-
由于许多人还不会申请key,所以添加此gif,注意此gif只添加了android debug key.如果app已经有签名文件,就一并把release key申请了,如下图.

- 如果已经有了release keystore.则按如下方式申请正式版android key
还不会生成正式版keystore,看这里

最快捷的测试方法

declare var LocationPlugin;
test(){
LocationPlugin.getLocation(data => {
alert(JSON.stringify(data))
}, msg => {
alert(JSON.stringify(msg))
});
}

封装插件
如下图,创建一个provider封装插件,注意红色标注
/**
* Created by yanxiaojun617@163.com on 12-27.
*/
import {Injectable} from '@angular/core';
import {Platform} from 'ionic-angular';
declare var LocationPlugin;
declare var AMapNavigation;
@Injectable()
export class NativeService {
private loading;
constructor(private platform: Platform) {
}
/**
* 是否真机环境
* @return {boolean}
*/
isMobile() {
return this.platform.is('mobile') && !this.platform.is('mobileweb');
}
/**
* 获得用户当前坐标
* @return {Promise<T>}
*/
getUserLocation() {
return new Promise((resolve, reject) => {
if (this.isMobile()) {
LocationPlugin.getLocation(data => {
resolve({'lng': data.longitude, 'lat': data.latitude});
}, msg => {
console.error('定位错误消息' + msg);
alert(msg.indexOf('缺少定位权限') == -1 ? ('错误消息:' + msg) : '缺少定位权限,请在手机设置中开启');
reject('定位失败');
});
} else {
console.log('非手机环境,即测试环境返回固定坐标');
resolve({'lng': 113.350912, 'lat': 23.119495});
}
});
}
/**
* 地图导航
* @param startPoint 开始坐标
* @param endPoint 结束坐标
* @param type 0实时导航,1模拟导航,默认为模拟导航
* @return {Promise<T>}
*/
navigation(startPoint, endPoint, type = 1) {
return new Promise((resolve, reject) => {
if (this.platform.is('mobile') && !this.platform.is('mobileweb')) {
AMapNavigation.navigation({
lng: startPoint.lng,
lat: startPoint.lat
}, {
lng: endPoint.lng,
lat: endPoint.lat
}, type, function (message) {
resolve(message);//非手机环境,即测试环境返回固定坐标
}, function (message) {
alert('导航失败:' + message);
reject('导航失败');
});
} else {
console.log('非手机环境不能导航');
}
});
}
}

在app中使用插件
-
在
app.module.ts
中注入NativeService
provider
-
在组件中使用,更完整代码在github查看
常见问题
1.定位权限问题
使用cordova.plugins.diagnostic中的isLocationAuthorized
方法可以判断app是否有定位权限.
使用cordova.plugins.diagnostic中的isLocationEnabled
方法可以判断app是否开启位置服务.
根据这两个方法就可以友好的提示用户开启定位权限,目前我的app已经实现此功能,详情看NativeService.ts中getUserLocation方法
如果不想使用diagnostic插件判断这么复杂,那就给config.xml
添加
<preference name="android-minSdkVersion" value="16" />
<preference name="android-maxSdkVersion" value="22"/>
<preference name="android-targetSdkVersion" value="22"/>
Android 6.0权限说明,Android 6.0系统默认为targetSdkVersion小于23的应用默认授予了所申请的所有权限,当targetSdkVersion大于23需要自己实现动态权限申请功能
![]()
2.导航功能和极光推送插件冲突
删除/plugins/cordova-plugin-jcore/plugin.xml中的引用

2.导航功能和cordova-sqlite-storage插件冲突
3.和插件冲突说明
- android查找.so文件会先看有没有arm64-v8a文件夹,如果没有该文件夹就去找armeabi-v7a文件夹,如果没有再去找armeabi文件夹.所以这三个文件夹有优先顺序.并且如果找到了就不再往下找了.
- 导航插件所有的.so文件都放在armeabi文件夹下,所以如果其他插件提供了arm64-v8a或者armeabi-v7a文件夹,那就找不到导航插件的.so文件了.所以导航功能会闪退
- 目前处理的方法就是不需要arm64-v8a和armeabi-v7a文件夹,具体操作就是注释其他插件plugin.xml中
target-dir="libs/arm64-v8a"
和target-dir="libs/armeabi-v7a"
的记录
网友评论
<platform name="ios">
<config-file parent="/*" target="config.xml">
<feature name="LocationPlugin">
<param name="ios-package" value="LocationPlugin"/>
</feature>
</config-file>
<config-file target="*/*-Info.plist" parent="UIBackgroundModes">
<array>
<string>location</string>
</array>
</config-file>
<config-file target="*/*-Info.plist" parent="NSLocationAlwaysAndWhenInUseUsageDescription">
<string>为了确保您可以正确使用本应用,请选择允许</string>
</config-file>
<config-file target="*/*-Info.plist" parent="NSLocationWhenInUseUsageDescription">
<string>为了确保您可以正确使用本应用,请选择允许</string>
</config-file>
<source-file src="src/ios/LocationPlugin.m"/>
</platform>
我都查过了SHA码都是对的
自己打包成ios app 发现 当应用程序按home页返回手机桌面 或者一段时间锁屏以后
获取经纬度的方法就无效了.
但是android打包后没有这个问题.. 请问您有遇到过吗
还有如果使用你的插件 ionic3 可以直接使用吗
现在有个问题就是锁屏以后 大概10秒 设置定时器的获取地理位置的方法就不执行了...
cp: copyFileSync: could not write to dest file (code=ENOENT):/projectPath/commandApp/platforms/android/res/xml/config.xml
(node:47746) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: ENOENT: no such file or directory, open projectPath/platforms/android/res/xml/config.xml'
.get('MapSearchHistory')第一次获取肯定是空,搜索成功后才会往里面存数据。
<config-file target="AndroidManifest.xml" parent="/manifest/application">
<meta-data android:name="com.amap.api.v2.apikey" android:value="67c8cb260aea6740bba40d64c0d94bc1"/>
</config-file>
<config-file target="AndroidManifest.xml" parent="/manifest/application">
<meta-data android:name="com.amap.api.v2.apikey" android:value="key">67c8cb260aea6740bba40d64c0d94bc1</meta-data>
</config-file>
这里两种配置都试过,报同样的错误!
2.在模拟器下虽然有上面的警告,但是能返回经纬度,而位置信息就不能返回了,position下面没有address这个字段
请问如何解决?
Plugin should use a background thread这个警告也有,但不影响定位
ios没有返回地址详情,地理反编码参考这里.
http://lbs.amap.com/api/javascript-api/example/geocoder/regeocoding
http://blog.csdn.net/wangqinglei0307/article/details/54632571
然后使用代码对比工具对比代码https://www.jianshu.com/p/081f7778523e
我使用了您的插件之后,按照上面所说 将 Android的 appkey 写在plugin.xml中 但是运行 ionic cordova build andorid --release --prod 之后,在/plarforms/android/AndroidManifest.xml中的 <meta-data android:name="com.amap.api.v2.apikey" android:value="这里填您申请的高德地图android key" /> 这里面的key还是没有变成我自己申请的。还请博主帮忙看看。万分感谢
再次感谢楼主的辛苦工作
<preference name="android-minSdkVersion" value="16" />
<preference name="android-maxSdkVersion" value="22" />
<preference name="android-targetSdkVersion" value="22" />
gaodeCmdTest(){
LocationPlugin.getLocation(data => {
console.log(JSON.stringify(data))
}), msg => {
console.log(JSON.stringify(msg))
}
}
调用该方法 报LocationPlugin 未定义。 请问 是哪里出错了呢
290558535
<script type="text/javascript" src="http://webapi.amap.com/maps?v=1.4.0&key=xxx";></script>
<preference name=xxx" value="xx"></preference> ? 这行代码自己加上去就可以了吗?
marker.on('click', function (e) {
//....
});
看这里第18行.https://github.com/yanxiaojun617/ionic2_tabs/blob/master/src/index.html
定位方法mapLocation写在:ngAfterContentInit() {
this.loadMap();
setTimeout(() => {
if (!this.map) {
this.loadMap();
}
}, 5000);
this.mapLocation();
// this.initMarker();
}
constructor(public testService: TestService,
private nativeService: NativeService,
private navCtrl: NavController,
private geolocation: Geolocation,
private modalCtrl: ModalController,
private platform: Platform
) {
this.tab = this.navCtrl.parent;
this.platform.ready().then((readySource) => {
console.log('Platform ready from', readySource);
this.mapLocation();
});
}
<meta-data android:name="com.amap.api.v2.apikey" android:value="d2bf7fc2e51f6fd2e13038b9a8346f40" />
<service android:name="com.amap.api.location.APSService" />
<meta-data android:name="com.amap.api.v2.apikey" android:value="这里填您申请的高德地图android key" />
<config-file target="AndroidManifest.xml" parent="/manifest/application">
<!--您申请的高德地图android key更多详情请看http://www.jianshu.com/p/85aceaee3b35-->
<meta-data android:name="com.amap.api.v2.apikey" android:value="027953419a4b48b45c476c4e04515ada"/>
</config-file>
ERROR ReferenceError: LocationPlugin is not defined
at LoginPage.webpackJsonp.295.LoginPage.ionViewDidLoad (login.ts:24)
at ViewController._lifecycle (view-controller.js:566)
at ViewController._didLoad (view-controller.js:439)
at NavControllerBase._didLoad (nav-controller-base.js:950)
at t.invoke (polyfills.js:3)
at Object.onInvoke (core.es5.js:4149)
at t.invoke (polyfills.js:3)
at r.run (polyfills.js:3)
at NgZone.run (core.es5.js:4017)
at NavControllerBase._viewAttachToDOM (nav-controller-base.js:592)
Error: Failed to fetch plugin https://github.com/yanxiaojun617/com.kit.cordova.
maplocation via registry.
Probably this is either a connection problem, or plugin spec is incorrect.
Check your connection and plugin name/version/URL.
Error: cmd: Command failed with exit code 4294963228 Error output:
npm ERR! addLocal Could not install C:\Users\ADMINI~1\AppData\Local\Temp\npm-22
4-7a03c1d9\git-cache-0f0782f8\a6a0fe1484d4f34783b73b40ce9706adc795a436
npm ERR! Windows_NT 6.1.7601
npm ERR! argv "D:\\IDE\\nodejs\\node.exe" "D:\\IDE\\nodejs\\node_modules\\npm\\
in\\npm-cli.js" "install" "https://github.com/yanxiaojun617/com.kit.cordova.ama
location" "--save"
npm ERR! node v6.10.3
npm ERR! npm v3.10.10
npm ERR! code EISDIR
npm ERR! errno -4068
npm ERR! syscall read
npm ERR! eisdir EISDIR: illegal operation on a directory, read
npm ERR! eisdir This is most likely not a problem with npm itself
npm ERR! eisdir and is related to npm not being able to find a package.json in
npm ERR! eisdir a package you are trying to install.
npm ERR! Please include the following file with any support request:
npm ERR! D:\IonicWorkSpace\swc_mobile_project\node_modules\npm-debug.log
这个是什么原因
cordova plugin add https://github.com/yanxiaojun617/com.kit.cordova.amaplocation --save
有提示报错么?为啥我的提示错误,安装不成功。
规划路径错误:ErrorDomain=AmapNaviErrorDomainCode=3 "CalculateRouteError:3;"
UserInfo={NsLocalizedDescription=CalculateRouteError:3;}
用高德javascript api
http://lbs.amap.com/api/javascript-api/example/geocoder/regeocoding
安装定位和导航插件的时候安不上 老是报错
Cannot find module '@ionic-native/file-opener'.
D:/ionic2_tabs-master/src/app/app.module.ts
import {FileTransfer} from "@ionic-native/file-transfer";
import {FileOpener} from '@ionic-native/file-opener';
import {InAppBrowser} from "@ionic-native/in-app-browser";
Typescript Error
Cannot find module '@ionic-native/http'.
D:/ionic2_tabs-master/src/app/app.module.ts
import {Diagnostic} from "@ionic-native/diagnostic";
import {HTTP} from '@ionic-native/http';
import {NativeService} from "../providers/NativeService";
Typescript Error
Module '"D:/ionic2_tabs-master/node_modules/ion2-calendar/dist/index"' has no exported member 'CalendarModalOptions'.
D:/ionic2_tabs-master/src/pages/demo/calendar-demo/calendar-demo.ts
import {NativeService} from "../../../providers/NativeService";
import {CalendarModalOptions, CalendarModal} from 'ion2-calendar'
Typescript Error
Module '"D:/ionic2_tabs-master/node_modules/ion2-calendar/dist/index"' has no exported member 'CalendarModal'.
D:/ionic2_tabs-master/src/pages/demo/calendar-demo/calendar-demo.ts
import {NativeService} from "../../../providers/NativeService";
import {CalendarModalOptions, CalendarModal} from 'ion2-calendar'
Typescript Error
Cannot find module 'echarts'.
D:/ionic2_tabs-master/src/pages/demo/echarts-demo/echarts-demo.ts
import {NavController, NavParams} from 'ionic-angular';
import ECharts from 'echarts';
import {NativeService} from "../../../providers/NativeService";
Typescript Error
Module '"D:/ionic2_tabs-master/src/model/UserInfo"' has no exported member 'LoginInfo'.
D:/ionic2_tabs-master/src/pages/login/LoginService.ts
import {Observable} from "rxjs";
import {LoginInfo} from "../../model/UserInfo";
Typescript Error
Cannot find module '@ionic-native/http'.
<preference name="android-targetSdkVersion" value="22"/>
使用这个打包安装不了
求救啊博主。实在不知道哪里的问题了
view: new AMap.View2D({//创建地图二维视口
zoom: 11 //设置地图缩放级别
})
});
你是不是没有new AMap.View2D?
也可以这样试试:注意添加了baseRender
new AMap.Map('map_container', {
zoom: 11, //设置地图缩放级别
baseRender:'d'
});
哇哦,博主星期天也在啊,刚才一直在查资料,直接获取定位的代码不能写在ionViewDidEnter里面,应该写在cordova插件就绪以后
constructor(public platform: Platform, private nativeService: NativeService) {
this.platform.ready().then((readySource) => {
console.log('Platform ready from', readySource);
this.getLocation();
});
}
getLocation() {
this.nativeService.getUserLocation().then(position =>
{
//alert(position);
//this.map.clearMap();
this.map = new AMap.Map(this.map_container.nativeElement, {
view: new AMap.View2D({//创建地图二维视口
zoom: 11, //设置地图缩放级别
rotateEnable: true,
showBuildingBlock: true
})
});
this.map.on('complete', function () {
//this.getLocation();
//that.mapIsComplete = true;
AMap.plugin(['AMap.ToolBar', 'AMap.Scale'], function () {//添加工具条和比例尺
this.map.addControl(new AMap.ToolBar());
this.map.addControl(new AMap.Scale());
});
});
window['HomeAMap'] = this.map;
this.marker = new AMap.Marker({
map: this.map,
position: new AMap.LngLat(position['lng'], position['lat'])
});
this.map.setFitView();
this.map.setZoom(16);
}).catch((error) =>
{
alert(error);
//this.getLocation();
});
}
经过测试应该没问题了
还有个疑问
ngOnInit() {
setTimeout(() => this.loadMap(), 1000);//1秒后加载地图
let loadNum = 0;
let interval = setInterval(() => {//10秒后检测地图是否加载成功
if (!this.map && loadNum < 5) {
this.loadMap();
} else {
clearInterval(interval);
this.getLocation();
}
}, 1000);
}
这个循环是什么意思?map回出现初始化错误么?我在本机上没有跑出这个错误来
针对你的问题,我写了如下代码并在真机调试,但是没有发现你这个情况,你不妨运行我的app在手机上测试
ionViewDidEnter() {
this.nativeService.getUserLocation().then(res=>{
alert(res['lng']+','+res['lat']);
},err=>{
alert(err);
})
}
不知道可有相关资料,十分感谢。