mui框架针对手机获取经纬度信息,其实做的可以,华为荣耀系列手机以及小米手机可以正常通过
plus.geolocation.getCurrentPosition
进行获取经纬度信息,但对于其他类型手机Android版本为5.1的则会存在不兼容的情况,导致调用上面的代码直接进入失败回调。
针对不同手机型号和系统版本,本宝宝做了个插件,测试还行,但手上机型不多,还请大家广提建议,现在上代码
package com.demo.maps;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;
import io.dcloud.common.DHInterface.IWebview;
import io.dcloud.common.DHInterface.StandardFeature;
import io.dcloud.common.util.JSUtil;
/**
* 测试获取手机经纬度信息插件
*
* @author 香蕉不拿拿
* @date 2018年6月19日 上午9:45:34
*/
public class Get_Longitude_Latitude extends StandardFeature{
private static final String TAG = "Get_Longitude_Latitude";
private Location location;
String callbackid;
IWebview pWebviews;
Activity activity;
// 位置管理器
LocationManager locationManager;
private String locationProvider;
public void getLongitudeAndLatitude(IWebview pWebview, JSONArray array) {
Log.i("成功进入--->", "getLongitudeAndLatitude");
pWebviews = pWebview;
activity = pWebview.getActivity();
callbackid = array.optString(0);
JSONArray jsonArray = null;
try {
jsonArray = new JSONArray(array.optString(1));
checkAndGetLocation();
} catch (JSONException e) {
// json数据异常
Log.i(TAG, "json数据异常");
e.printStackTrace();
}
}
public void checkAndGetLocation() {
// 1.获取位置信息管理器
locationManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE);
if(locationManager == null) {
Log.i(TAG, "locationManager不存在");
return;
}
// 2.获取位置信息提供器,Gps或network
List<String> providers = locationManager.getProviders(true);
if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
// 如果是网络定位
Log.i(TAG, "网络定位");
locationProvider = LocationManager.NETWORK_PROVIDER;
} else if (providers.contains(LocationManager.GPS_PROVIDER)) {
// 如果是GPS定位
Log.i(TAG, "GPS定位");
locationProvider = LocationManager.GPS_PROVIDER;
} else {
Log.i(TAG, "没有可用的位置提供器");
//若不开启位置服务 则会导致无法获取手机当前的经纬度信息(使用回调提示用户手动开启位置服务)
return;
}
// 3.获取上次的位置,一般第一次运行,此值为null
Log.i(TAG, "开始进行第一次获取");
Location location = locationManager.getLastKnownLocation(locationProvider);
if (location != null) {
setLocation(location);
}else {
Log.i(TAG, "开始进行第二次获取");
SystemClock.sleep(1000);
Log.i(TAG, "第二次获取依旧为null");
location = locationManager.getLastKnownLocation(locationProvider);
if (location != null) {
setLocation(location);
}else {
//quit操作
Log.i(TAG, "第二次获取依旧为null");
}
}
// 监视地理位置变化,第二个和第三个参数分别为更新的最短时间minTime和最短距离minDistace
//locationManager.requestLocationUpdates(locationProvider, 5000, 3, locationListener);
}
private void setLocation(Location location) {
this.location = location;
String address = "纬度:" + location.getLatitude() + "经度:" + location.getLongitude();
Log.i(TAG, address);
JSUtil.execCallback(pWebviews, callbackid, address, JSUtil.OK, true);
}
/**
* LocationListern监听器 参数:地理位置提供器、监听位置变化的时间间隔、位置变化的距离间隔、LocationListener监听器
*/
LocationListener locationListener = new LocationListener() {
/**
* 当某个位置提供者的状态发生改变时
*/
@Override
public void onStatusChanged(String provider, int status, Bundle arg2) {
}
/**
* 某个设备打开时
*/
@Override
public void onProviderEnabled(String provider) {
}
/**
* 某个设备关闭时
*/
@Override
public void onProviderDisabled(String provider) {
}
/**
* 手机位置发生变动
*/
@Override
public void onLocationChanged(Location location) {
location.getAccuracy();// 精确度
setLocation(location);
}
};
}
我注释掉了监听位置改变的代码,这个对于混合开发个人觉得不需要,原生app开发需要的。
测试如果发现未进入网络获取信息或者gps位置信息,直接进入else判断流程,一般情况下是用户关闭了位置服务,这时需要手动或自动开启位置服务!
针对app有位置权限,但用户手动关闭了位置服务时,代码需要使用如下所示:
package com.demo.maps; import java.util.List; import org.json.JSONArray; import org.json.JSONException; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.os.Handler; import android.os.SystemClock; import android.util.Log; import io.dcloud.common.DHInterface.IWebview; import io.dcloud.common.DHInterface.StandardFeature; import io.dcloud.common.util.JSUtil; /** * 测试获取手机经纬度信息插件 * 传值getlocation表示获取经纬度信息 * @author 香蕉不拿拿先生 * @date 2018年6月19日 上午9:45:34 * */ @SuppressLint("NewApi") public class Get_Longitude_Latitude extends StandardFeature { private static final String TAG = "Get_Longitude_Latitude"; private Location location; String callbackid; IWebview pWebviews; Activity activity; // 位置管理器 LocationManager locationManager; private String locationProvider; public void getLongitudeAndLatitude(IWebview pWebview, JSONArray array) { Log.i("成功进入--->", "getLongitudeAndLatitude"); pWebviews = pWebview; activity = pWebview.getActivity(); callbackid = array.optString(0); JSONArray jsonArray = null; try { jsonArray = new JSONArray(array.optString(1)); String operateName = jsonArray.getString(0); Log.i(TAG, operateName); if (checkPermission()) { if ("getlocation".equals(operateName)) { // 当有位置权限信息 且 用户未主动关闭位置权限时,可以调用此方法获取经纬度信息 getLocation(); } } else { // 在checkPermission()中有对false的返回进行相关的提示操作 } } catch (JSONException e) { // json数据异常 Log.i(TAG, "json数据异常"); JSUtil.execCallback(pWebviews, callbackid, "JAON_EXCEPTION", JSUtil.OK, true); e.printStackTrace(); } } // 个人觉得在使用定位插件之前 优先判断用户是否给予了位置权限 public boolean checkPermission() { // 0 /* * if (activity.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) * == PackageManager.PERMISSION_DENIED) { // -1 Log.i(TAG, "无权限"); return false; * } */ // 1.获取位置信息管理器 locationManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE); if (locationManager == null) { Log.i(TAG, "locationManager不存在"); JSUtil.execCallback(pWebviews, callbackid, "NO_LOCATIONMANAGER", JSUtil.OK, true); return false; } boolean gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); Log.i(TAG, String.valueOf(gps)); boolean network = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); Log.i(TAG, String.valueOf(network)); // 当用户未开启位置服务时(有权限,但用户在手机管理中进行了关闭操作),则会出现无法定位的问题 if (!(gps || network)) { // 提示用户开启位置服务 JSUtil.execCallback(pWebviews, callbackid, "REMAIN_OPEN_LOCATION_SERVICE", JSUtil.OK, true); return false; } else { return true; } } // 获取位置信息 public void getLocation() { // 2.获取位置信息提供器,Gps或network(优先网络定位) List<String> providers = locationManager.getProviders(true); if (providers.contains(LocationManager.NETWORK_PROVIDER) || providers.contains(LocationManager.GPS_PROVIDER)) { if (providers.contains(LocationManager.NETWORK_PROVIDER)) { // 如果是网络定位 Log.i(TAG, "网络定位"); JSUtil.execCallback(pWebviews, callbackid, "NET_WORK", JSUtil.OK, true); locationProvider = LocationManager.NETWORK_PROVIDER; } //gps放在后面是因为若用户开启了高精度gps定位,就采用gps if (providers.contains(LocationManager.GPS_PROVIDER)) { // 如果是GPS定位 Log.i(TAG, "GPS定位"); JSUtil.execCallback(pWebviews, callbackid, "GPS", JSUtil.OK, true); locationProvider = LocationManager.GPS_PROVIDER; } } else { Log.i(TAG, "没有可用的位置提供器"); // 若不开启位置服务 则会导致无法获取手机当前的经纬度信息 JSUtil.execCallback(pWebviews, callbackid, "NO_LOCATION_SERVICE", JSUtil.OK, true); return; } // 3.获取上次的位置,一般第一次运行,此值为null Log.i(TAG, "开始进行第一次获取"); Location location = locationManager.getLastKnownLocation(locationProvider); if (location != null) { setLocation(location); } else { Log.i(TAG, "开始进行第二次获取"); SystemClock.sleep(1000); Log.i(TAG, "第二次获取依旧为null"); location = locationManager.getLastKnownLocation(locationProvider); if (location != null) { setLocation(location); } else { // 第二次还是null 判断最开始使用的是gps还是网络 如果是gps就改为网络 继续定位 if(locationProvider == LocationManager.GPS_PROVIDER) { //开始为gps,但对象为null 改用网络 定位(考虑到室内开gps后 location对象为null的情况) locationProvider = LocationManager.NETWORK_PROVIDER; }else{ Log.i(TAG, "第二次获取依旧为null"); JSUtil.execCallback(pWebviews, callbackid, "LOCATION_NULL", JSUtil.OK, true); return; } location = locationManager.getLastKnownLocation(locationProvider); } } /** * 调用位置监听 参数一:位置提供器的类型(gps、网络等) 参数二:监听位置变化的时间间隔,以ms为单位 参数三:监听位置变化的距离间隔,以m为单位 * 参数四:回调函数 */ locationManager.requestLocationUpdates(locationProvider, 3000, (float) 0.5, locationListener); //插件是异步的 ,退出H5页面后(插件调用了的) 此监听依旧在进行-----设置时间段 new Handler().postDelayed(new Runnable() { @Override public void run() { Log.i(TAG, "定时器执行"); //locationListener为null是出现:java.lang.IllegalArgumentException if(locationManager != null && locationListener != null) { //移除监听器 locationManager.removeUpdates(locationListener); } } }, 1000*10); } private void setLocation(Location location) { this.location = location; String address = "LATIDUTE-" + location.getLatitude() + "==LONGTIDUTE-" + location.getLongitude(); Log.i(TAG, address); // JSUtil.execCallback(pWebviews, callbackid, address, JSUtil.OK, true); } /** * LocationListern监听器 参数:地理位置提供器、监听位置变化的时间间隔、位置变化的距离间隔、LocationListener监听器 */ LocationListener locationListener = new LocationListener() { /** * 当某个位置提供者的状态发生改变时 */ @Override public void onStatusChanged(String provider, int status, Bundle arg2) { } /** * 某个设备打开时 */ @Override public void onProviderEnabled(String provider) { } /** * 某个设备关闭时 */ @Override public void onProviderDisabled(String provider) { } /** * 手机位置发生变动 */ @SuppressWarnings("unused") @Override public void onLocationChanged(Location location) { location.getAccuracy();// 精确度 // setLocation(location); Log.i(TAG, "位置发生改变回调"); if (location != null) { String address = "LATIDUTE-" + location.getLatitude() + "==LONGTIDUTE-" + location.getLongitude(); Log.i(TAG, address); JSUtil.execCallback(pWebviews, callbackid, address, JSUtil.OK, true); } } }; }
光判断是否存在权限依旧是不够的,经过测试发现当有权限,但用户主动关闭,会导致依旧无法获取经纬度信息的问题,所以添加了判断LocationManager.GPS_PROVIDER和LocationManager.NETWORK_PROVIDER,当用户手动关闭位置服务,两者均会返回false,反之两者都是true(本人手机的测试结果,不代表全部,所以用的"||")
混合开发,插件js部分
document.addEventListener("plusready",function(){ // 声明的JS“扩展插件别名” var _BARCODE = 'checkAndGetLocation', B = window.plus.bridge; var checkAndGetLocation = { getLongitudeAndLatitude:function(Argus,successCallback,errorCallback){ var success = typeof successCallback !== 'function' ? null : function(args) { successCallback(args); }, fail = typeof errorCallback !== 'function' ? null : function(code) { errorCallback(code); }; callbackID = B.callbackId(success, fail); return B.exec(_BARCODE, "getLongitudeAndLatitude", [callbackID, Argus]); } }; window.plus.checkAndGetLocation = checkAndGetLocation; },true)