网页定位的不足

我之前写了篇vue调用百度地图 js api实现定位的文章,
vue 实现定位到当前位置
但是实际使用的时候,发现百度定位js经常定位不精确,这个不足,官网也有提,

为了精确,还是使用原生app调用高德地图api来实现定位,这样就要用到js与原生的交互,js调用某个方法,然后触发原生的定位,原生定位完成,调用js方法,回传给js,我这边做的兼容性比较高,js传入不同的坐标系,原生会在回传给js的方法中,将坐标系转换

实现

vue定义方法
vue定义两个方法,方法getLocationFromNative(String type),调起定位功能,type是坐标类型,默认gcj02,bd09:百度坐标系,gcj02:火星坐标系,gps:GPS坐标系(WGS84坐标系),原生提供根据type,转换坐标系的方法
定位成功或失败,回调notifyLocationFromApp,传入json数据,json数据自己组装,我这边是这样的

{"data":{"address":"xxx","city":"xx市",
"country":"中国","description":"在xx附近","district":"xx区","latitude":31.4xx8,
"locationDetail":"#csid:4d4xxx7039e594xx3",
"longitude":120.30xx1,"province":"xx省","street":"xx大道","streetNum":"xx号"}
,"isOk":true}
<template><div class="phoneContant"><a :href="tel">点击拨打电话</a><van-button type="warning" @click="goToNext">进入下一页</van-button><van-button type="warning" @click="getLocation">从app获取定位</van-button></div>
</template><script>
//判断是否是安卓还是ios
var config = {isAndroid: /Android/i.test(navigator.userAgent), //判断是否为移动端isIos: !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //判断是否为IOS
};
export default {name: "Home",data() {return {msg: "我是首页",store_info: {phone: 15xxxx753,},nativeLocationSuccess:false,loadDefault:false};},methods: {goToNext() {this.$router.push("/second");},getLocation() {setTimeout(() => {if(this.nativeLocationSuccess==false){console.log("定位失败,加载默认的接口");this.loadDefault=true}}, 10000);//10秒未返回数据,加载默认的,防止前端没有getLocationFromNative和notifyLocationFromApp回调/*** 经纬度坐标系,默认gcj02bd09:百度坐标系gcj02:火星坐标系gps:GPS坐标系(WGS84坐标系)*/if (config.isAndroid && window.hesAndroidNative) {window.hesAndroidNative.getLocationFromNative("");} else if (config.isIos && window.webkit) {window.webkit.messageHandlers.getLocationFromNative.postMessage("");} else {}},notifyLocationFromApp(jsonStr) {this.nativeLocationSuccess=true;if(this.loadDefault==true){return}console.log("json string" + jsonStr);let valueObj=JSON.parse(jsonStr)console.log("valueObj " + valueObj);let value = jsonStr+"||||测试解析结果:"+valueObj.data.addressif(valueObj.isOk==false){console.log("失败");}else{console.log("成功",valueObj.data.longitude, valueObj.data.latitude);}this.$dialog.alert({confirmButtonText: "是",closeOnClickOverlay: false,title: "提示",showCancelButton: false,messageAlign: "center",message: value,}).then(() => {return false;}).catch(() => {});},},computed: {tel() {return "tel:" + Number(this.store_info.phone);},},created() {window.notifyLocationFromApp = this.notifyLocationFromApp;this.getLocation()},
};
</script><style>
</style>

大概逻辑就是进入页面调用原生的定位,然后等待10s,10秒未返回数据,加载默认的,防止前端没有getLocationFromNative和notifyLocationFromApp回调,因为js如果检测到方法未定义,直接报错,也没回调,这样写,能保证程序正常运行
原生实现

public class WebviewBase extends BaseCompatActivity{@BindView(R.id.iv_back)protected ImageView ivBack;@BindView(R.id.iv_close)protected ImageView ivClose;@BindView(R.id.tv_title)protected TextView tvTitle;@BindView(R.id.rl_top)protected  RelativeLayout rlTop;@BindView(R.id.pbar_more)protected ProgressBar progressBar;@BindView(R.id.webView)protected WebView webView;protected LocationReslut locationReslut=new LocationReslut();protected AMapLocationClient mLocationClient = null;protected String locationType="";protected AMapLocationListener mLocationListener = new AMapLocationListener(){@Overridepublic void onLocationChanged(AMapLocation aMapLocation){if (aMapLocation != null){if (aMapLocation.getErrorCode() == 0){LocationReslut.Data locationData=locationReslut.new Data();locationData.setAddress(aMapLocation.getAddress());locationData.setCity(aMapLocation.getCity());locationData.setCountry(aMapLocation.getCountry());locationData.setStreetNum(aMapLocation.getStreetNum());locationData.setStreet(aMapLocation.getStreet());locationData.setDistrict(aMapLocation.getDistrict());locationData.setProvince(aMapLocation.getProvince());locationData.setLatitude(aMapLocation.getLatitude());locationData.setLongitude(aMapLocation.getLongitude());locationReslut.setData(locationData);locationReslut.setOk(true);locationResultToJs();mLocationClient.stopLocation();}else{locationResultToJs();Log.e("定位错误", aMapLocation.getErrorCode() + ":" + aMapLocation.getErrorInfo());}}else{locationResultToJs();Log.e("定位失败", "");}}};private void locationResultToJs() {Gson gson = new Gson();Log.i("location",gson.toJson(locationReslut));LocationReslut.Data data=locationReslut.getData();if(locationReslut.isOk){double[] gps=null;switch (locationType){case "bd09":gps= GPSUtil.gcj02_To_Bd09(data.getLatitude(),data.getLongitude());data.setLatitude(gps[0]);data.setLongitude(gps[1]);break;case "gps":gps= GPSUtil.gcj02_To_Gps84(data.getLatitude(),data.getLongitude());data.setLatitude(gps[0]);data.setLongitude(gps[1]);break;default:break;}}//原生回调js通知webView.evaluateJavascript("javascript:notifyLocationFromApp('" + gson.toJson(locationReslut) + "')", new ValueCallback<String>() {@Overridepublic void onReceiveValue(String value) {//此处为 js 返回的结果}});}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_webview_privacy);ButterKnife.bind(this);initWebView();init();locationReslut.setData(null);locationReslut.setOk(false);....省略各种初始化方法}protected void init(){mLocationClient = new AMapLocationClient(WebviewBase.this);mLocationClient.setLocationListener(mLocationListener);if (ActivityCompat.checkSelfPermission(WebviewBase.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){ActivityCompat.requestPermissions(WebviewBase.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 100);}else{//mLocationClient.startLocation();}}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults){super.onRequestPermissionsResult(requestCode, permissions, grantResults);}private void initWebView() {WebSettings webSettings = webView.getSettings();webSettings.setJavaScriptEnabled(true);// 设置字符编码webSettings.setDefaultTextEncodingName("utf-8");webSettings.setJavaScriptCanOpenWindowsAutomatically(true);webSettings.setAllowFileAccess(true);webSettings.setLoadsImagesAutomatically(true);// webSettings.setAppCacheEnabled(true);webSettings.setBlockNetworkImage(false);// webSettings.setGeolocationEnabled(true);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);}webSettings.setDefaultTextEncodingName("UTF-8");webSettings.setSupportZoom(true);// webSettings.setBuiltInZoomControls(true);// webSettings.setPluginsEnabled(true);//webView.addJavascriptInterface(this, "AppInterface");webSettings.setDomStorageEnabled(true);webSettings.setDatabaseEnabled(true);final String dbPath = getApplicationContext().getDir("db", Context.MODE_PRIVATE).getPath();webSettings.setDatabasePath(dbPath);final String cachePath = getApplicationContext().getDir("cache", Context.MODE_PRIVATE).getPath();webSettings.setAppCachePath(cachePath);webSettings.setAppCacheMaxSize(10 * 1024 * 1024);//设置加载进来的页面自适应手机屏幕webSettings.setUseWideViewPort(true);webSettings.setLoadWithOverviewMode(true);webView.setWebChromeClient(new MyWebChromeClient());webView.setWebViewClient(new MyWebViewClient());if (userAgent != null && !StringUtil.isEmpty(userAgent)) {String ua = webSettings.getUserAgentString();// 获取默认的UAwebSettings.setUserAgentString(ua + "; " + userAgent);// UA追加自定义标识符}// 通过addJavascriptInterface()将Java对象映射到JS对象//参数1:Javascript对象名//参数2:Java对象名webView.addJavascriptInterface(new HesAndroidtoJs(), "hesAndroidNative");}// 继承自Object类public class HesAndroidtoJs {// 定义JS需要调用的方法// 被JS调用的方法必须加入@JavascriptInterface注解@JavascriptInterfacepublic void getDomainDataFromNative() {runOnUiThread(new Runnable() {@Overridepublic void run() {//原生回调js通知webView.evaluateJavascript("javascript:notifyDomainDataFromApp('" + domainData + "')", new ValueCallback<String>() {@Overridepublic void onReceiveValue(String value) {//此处为 js 返回的结果}});}});}/*** 经纬度坐标系,默认gcj02* bd09:百度坐标系* gcj02:火星坐标系* gps:GPS坐标系(WGS84坐标系)* @param type*/@JavascriptInterfacepublic void getLocationFromNative(String type) {locationType=type;if(mLocationClient!=null){mLocationClient.startLocation();}}}private class LocationReslut{private boolean isOk;private Data data;public boolean isOk() {return isOk;}public void setOk(boolean ok) {isOk = ok;}public Data getData() {return data;}public void setData(Data data) {this.data = data;}public class Data{String country;String province;String city;String street;String streetNum;String address;double latitude;double longitude;String district;public String getCountry() {return country;}public void setCountry(String country) {this.country = country;}public String getProvince() {return province;}public void setProvince(String province) {this.province = province;}public String getCity() {return city;}public void setCity(String city) {this.city = city;}public String getStreet() {return street;}public void setStreet(String street) {this.street = street;}public String getStreetNum() {return streetNum;}public void setStreetNum(String streetNum) {this.streetNum = streetNum;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public double getLatitude() {return latitude;}public void setLatitude(double latitude) {this.latitude = latitude;}public double getLongitude() {return longitude;}public void setLongitude(double longitude) {this.longitude = longitude;}public String getDistrict() {return district;}public void setDistrict(String district) {this.district = district;}}}@Overrideprotected void onDestroy() {super.onDestroy();if(mLocationClient!=null){mLocationClient.stopLocation();}}
}

GPSUtil

public class GPSUtil
{public static double pi = 3.1415926535897932384626;public static double x_pi = 3.14159265358979324 * 3000.0 / 180.0;public static double a = 6378245.0;public static double ee = 0.00669342162296594323;public static double transformLat(double x, double y){double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;return ret;}public static double transformLon(double x, double y){double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0 * pi)) * 2.0 / 3.0;return ret;}public static double[] transform(double lat, double lon){if (outOfChina(lat, lon)){return new double[]{lat, lon};}double dLat = transformLat(lon - 105.0, lat - 35.0);double dLon = transformLon(lon - 105.0, lat - 35.0);double radLat = lat / 180.0 * pi;double magic = Math.sin(radLat);magic = 1 - ee * magic * magic;double sqrtMagic = Math.sqrt(magic);dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);double mgLat = lat + dLat;double mgLon = lon + dLon;return new double[]{mgLat, mgLon};}public static boolean outOfChina(double lat, double lon){if (lon < 72.004 || lon > 137.8347)return true;if (lat < 0.8293 || lat > 55.8271)return true;return false;}/*** 84 to 火星坐标系 (GCJ-02) World Geodetic System ==> Mars Geodetic System** @param lat* @param lon* @return*/public static double[] gps84_To_Gcj02(double lat, double lon){if (outOfChina(lat, lon)){return new double[]{lat, lon};}double dLat = transformLat(lon - 105.0, lat - 35.0);double dLon = transformLon(lon - 105.0, lat - 35.0);double radLat = lat / 180.0 * pi;double magic = Math.sin(radLat);magic = 1 - ee * magic * magic;double sqrtMagic = Math.sqrt(magic);dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);double mgLat = lat + dLat;double mgLon = lon + dLon;return new double[]{mgLat, mgLon};}/*** * 火星坐标系 (GCJ-02) to 84 * * @param lon * @param lat * @return*/public static double[] gcj02_To_Gps84(double lat, double lon){double[] gps = transform(lat, lon);double lontitude = lon * 2 - gps[1];double latitude = lat * 2 - gps[0];return new double[]{latitude, lontitude};}/*** 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 将 GCJ-02 坐标转换成 BD-09 坐标** @param lat* @param lon*/public static double[] gcj02_To_Bd09(double lat, double lon){double x = lon, y = lat;double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);double tempLon = z * Math.cos(theta) + 0.0065;double tempLat = z * Math.sin(theta) + 0.006;double[] gps = {tempLat, tempLon};return gps;}/*** * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 * * 将 BD-09 坐标转换成GCJ-02 坐标 * * @param* bd_lat * @param bd_lon * @return*/public static double[] bd09_To_Gcj02(double lat, double lon){double x = lon - 0.0065, y = lat - 0.006;double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);double tempLon = z * Math.cos(theta);double tempLat = z * Math.sin(theta);double[] gps = {tempLat, tempLon};return gps;}/*** 将gps84转为bd09** @param lat* @param lon* @return*/public static double[] gps84_To_bd09(double lat, double lon){double[] gcj02 = gps84_To_Gcj02(lat, lon);double[] bd09 = gcj02_To_Bd09(gcj02[0], gcj02[1]);return bd09;}public static double[] bd09_To_gps84(double lat, double lon){double[] gcj02 = bd09_To_Gcj02(lat, lon);double[] gps84 = gcj02_To_Gps84(gcj02[0], gcj02[1]);//保留小数点后六位gps84[0] = retain6(gps84[0]);gps84[1] = retain6(gps84[1]);return gps84;}/*** 保留小数点后六位** @param num* @return*/private static double retain6(double num){String result = String.format("%.6f", num);return Double.valueOf(result);}}

总结

这个只是拿定位做个例子,其实这个就是原生和js交互的通用方法,可以直接使用,完成其他需要相互交互的逻辑

vue与安卓原生定位的交互相关推荐

  1. vue 获取安卓原生方法_vue与原生app的对接交互的方法(混合开发)

    小伙伴们在用vue开发h5项目特别是移动端的项目,很多都是打包后挂载在原生APP上的,那就少不了与原生交互了,我把我踩的一些坑,拿出来给大家分享下.1.通过url传输数据:(一般是在入口页面传下app ...

  2. vue 获取安卓原生方法_VUE H5调用原生APP方法实践笔记

    最近做与app端的混合开发,了解到了H5与原生app端之间的方法互通 首先是我们给app端定义方法供他们使用(以vue为例) methods中定义一个方法名称 VContent() { console ...

  3. android 原始定位,安卓原生定位

    var i=0;//执行次数 var chenggong=0;//成功次数 var shibai=0;//失败次数 mui.plusReady(function(){ var context = pl ...

  4. 安卓原生系统_全球首个原生安卓车载系统实测!操作流畅 可跟手机媲美

    ch共 看点:全球首个原生安卓汽车系统落在了Polestar 2上,到底能否带来质变呢? 车东西(公众号:chedongxi)编 | 吴垚 导语:Polestar 2作为沃尔沃旗下高端纯电动汽车,因其 ...

  5. 移动端h5页面与原生app的交互

    在js与原生进行交互的时候对js来说,大部分逻辑都是回调与监听,调用原生的方法 JSBridge是Native代码与JS代码的通信桥梁,因此项目中要设计jsbridge.js: (1)设计出一个Nat ...

  6. 华为手机怎么刷android系统,怎样刷入安卓原生系统 在手机系统更新这件事上,小米华为和OPPOvivo谁更有良心...

    原标题:在手机系统更新这件事上,小米华为和OPPOvivo谁更有良心? 用国产手机的朋友可能都有一种感受,对于系统升级这块,有的厂商很积极,但有的厂商却非常的不积极.比如小米,华为,一加等在系统升级方 ...

  7. Flutter 实现安卓原生系统级悬浮窗

    Flutter实现安卓原生系统级悬浮窗 原创:@As.Kai 博客地址:https://blog.csdn.net/qq_42362997 如果以下内容对您有帮助,点赞点赞点赞~ 最近碰到了一个需求 ...

  8. 安卓webview和h5交互

    先上html的代码: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <HTML& ...

  9. 封装一个类搞定90%安卓客户端与服务器端交互

    本实例封装了一个处理安卓客户端与服务器端交互的几个方法,对于中文乱码问题本实例也找到了解决方案.本例可以处理的场景如下: 1.与服务器端交互json数据. 2.Get方式与服务器端交互数据. 3.Po ...

最新文章

  1. ubuntu 发行版升级注意事项
  2. iOS架构-静态库.a之依赖第三方静态库.a的制作(8)
  3. 解决Chrome浏览器启动速度慢的问题
  4. 干货整理 Unity3D资源汇总
  5. win7优化设置_win7蓝牙怎么打开?
  6. Python库大全(涵盖了Python应用的方方面面),建议收藏留用!
  7. C++|Qt最简单的http的get请求
  8. KVM/QEMU libvirt 实践
  9. mysql varbinary blob_MySQL BIT、BINARY、VARBINARY、BLOB(二进制类型)
  10. R语言方差分解分析(Variation partition analysis)及其显著性检验
  11. word插入图片显示不全
  12. 【FPGA——工具篇】:Modelsim SE-64 10.4下载、破解、安装过程
  13. Arduino库的接口:Ticker库
  14. Apache Beam开发指南
  15. 微信开发者工具:单个安装微信开发者工具中没有的扩展(通过vsix 离线安装)
  16. 追求境界,毫无“线”制 NINEKA南卡T1真无线蓝牙耳机
  17. 【韩顺平Linux】学习笔记1
  18. 人工智能到底有多强大?
  19. 如何用计算机算时间,在win10电脑的计算器中如何进行日期的计算
  20. Python --- 笑脸检测+口罩人脸识别

热门文章

  1. php h5支付没有返回app中,很多人都不知道的监听微信、支付宝等移动app及浏览器的返回、后退、上一页按钮的事件方法...
  2. 未来十年计算机工程师,盘点未来十年最紧缺的6大职业
  3. java对象,属于你得地址找到了吗
  4. 一键提高工作效率,这4款软件是你的工作好帮手
  5. Chubby 的KeepAlive请求过程
  6. shell脚本中单引号和双引号
  7. 前端页面文字出现繁体字,乱码解决方案
  8. 用Opencv实时画运动轨迹的思路
  9. 推荐几种简洁美观的博客背景效果
  10. 自动批量裁剪+合成+整理正反向序列