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)