public void reStart() {
start(null);
}
@Override
public void stop() {
mProvider = null;
if(lm != null)
lm.removeUpdates(mChangeListener);
lm = null;
mListener = null;
mChangeListener = null;
}
@SuppressWarnings(“all”)
private String getLocation(String provider) {
if(provider == null)
return null;
lm.requestLocationUpdates(provider, mSiLoOption.time, mSiLoOption.distance, mChangeListener);
return provider;
}
class MyLocationListener implements LocationListener {
@Override
public void onLocationChanged(Location location) {
if(mProvider == null)
return;
latlng = location != null ? ConverHelper.loConverToLatlng(location) : latlng;
mListener.onSuccess(latlng);
if(mSiLoOption.isGpsFirst){
if(location != null){
if(mProvider == LocationManager.GPS_PROVIDER)
mCounter = 0;
else{
mCounter += mSiLoOption.time/1000;
if(mCounter > NET_TIME_SPACE){
mProvider = getLocation(Helper.getGPSProvider(lm));
mCounter = 0;
}
}
}else{
// gps无信号时,尝试network获取
mCounter += mSiLoOption.time/1000;
if(mCounter >= GPS_TIME_SPACE && mCounter < NET_TIME_SPACE){
mProvider = getLocation(Helper.getNetWorkProvider(lm));
}else if(mCounter > NET_TIME_SPACE){
// 只要最后一个net点失败,就抛出回调;前两个点,由于开始,可能为空,不做强制判断处理
mListener.onFail("location latlng = null , provider = "+ mProvider);
}
}
}else{
// 当network获取不到定位
if(location == null)
mListener.onFail("location latlng = null , provider = "+ mProvider);
}
}
@Override
public void onStatusChanged(String s, int state, Bundle bundle) {
if(mListener == null)
return;
if(Build.VERSION.SDK_INT > 28){
LogUtil.e(“after api 29 always AVAILABLE”);
}else{
switch (state){
case LocationProvider.OUT_OF_SERVICE:
case LocationProvider.TEMPORARILY_UNAVAILABLE:
LogUtil.e(“current provider out of condition”);
break;
}
}
}
@Override
public void onProviderEnabled(String s) {
}
@Override
public void onProviderDisabled(String s) {
}
}
public static class SiLoOption {
/**
- gps 优先否
*/
private boolean isGpsFirst = false;
/**
- 监听定位变化最短时间间隔,默认time s
*/
private int time = 2000;
/**
- 监听变化的最小距离
*/
private int distance = 10;
public boolean isGpsFirst() {
return isGpsFirst;
}
public SiLoOption setGpsFirst(boolean gpsFirst) {
isGpsFirst = gpsFirst;
return this;
}
public int getTime() {
return time;
}
public SiLoOption setTime(int time) {
this.time = time;
return this;
}
public int getRequestTepe() {
return distance;
}
public SiLoOption setRequestTepe(int requestTepe) {
this.distance = requestTepe;
return this;
}
}
}
获取经纬度代码:定位类
import android.content.Context;
import androidx.annotation.Nullable;
import com.mjzuo.location.constant.Constant;
import com.mjzuo.location.helper.GeReFactory;
import com.mjzuo.location.location.GoogleGeocoding;
import com.mjzuo.location.location.IGeocoding;
import com.mjzuo.location.util.LogUtil;
ic class GeocodingManager {
private IGeocoding mGeocoding;
private IGeocoding.ISiLoResponseListener mListener;
private Context mContext;
public GeocodingManager(Context context) {
mContext = context;
mGeocoding = GeReFactory.getGeocodingType(mContext, Constant.LM_API);
}
public GeocodingManager(Context context, @Nullable GeoOption option) {
mContext = context;
mGeocoding = GeReFactory.getGeocodingType(mContext, option.getGeoType());
if(mGeocoding instanceof GoogleGeocoding)
((GoogleGeocoding) mGeocoding).setSimpleLocationOption(option.getOption());
}
public void start(IGeocoding.ISiLoResponseListener listener) {
if(listener != null)
mListener = listener;
if(mListener == null){
LogUtil.e(“simple location response listener null”);
}
mGeocoding.start(mListener);
}
public void reStart(){
start(null);
}
public void stop(){
mGeocoding = null;
mListener = null;
}
public static class GeoOption {
/**
-
定位的类型
-
LocationManager或基站定位
*/
private int GeoType = Constant.LM_API;
/**
- 这是locationManager的配置类
*/
private GoogleGeocoding.SiLoOption option;
public int getGeoType() {
return GeoType;
}
public GeoOption setGeoType(int geoType) {
GeoType = geoType;
return this;
}
public GoogleGeocoding.SiLoOption getOption() {
return option;
}
public GeoOption setOption(GoogleGeocoding.SiLoOption option) {
this.option = option;
return this;
}
}
}
百度API接口:
import android.content.Context;
import android.os.AsyncTask;
import androidx.annotation.Nullable;
import com.mjzuo.location.ReverseGeocodingManager;
import com.mjzuo.location.bean.Latlng;
import com.mjzuo.location.constant.UrlConstant;
import com.mjzuo.location.helper.Helper;
import com.mjzuo.location.net.NetUtil;
import com.mjzuo.location.util.CommonUtil;
import com.mjzuo.location.util.LogUtil;
import org.json.JSONObject;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.LinkedHashMap;
import java.util.Map;
public class BaiduGeRe implements IReGe {
private String ak = “KHVTQZiP2UGuv7SkNbqYPKu4co7kbkS4”;
private String sk = “cTqIacm4uvDnQWpWWCZGElhbIx4Nxv3q”;
private String host = “/reverse_geocoding/v3/”;
private LinkedHashMap<String, String> paramsMap;
// 默认使用sn校验方式
private boolean isSn = true;
private MyAsyncTask task;
private IReGeListener mListener;
@Override
public void init(@Nullable Context context) {
paramsMap = new LinkedHashMap<>();
paramsMap.put(“ak”, ak);
paramsMap.put(“coordtype”, “wgs84ll”);
}
@Override
public void setOptions(@Nullable ReverseGeocodingManager.ReGeOption options) {
this.isSn = options.isSn();
if(options.getKey() != null && !options.getKey().isEmpty())
this.ak = options.getKey();
if(options.getSk() != null && !options.getSk().isEmpty())
this.sk = options.getSk();
}
@Override
public void reGeToAddress(Latlng latlng) {
paramsMap.put(“location”, latlng.getLatitude() + “,” + latlng.getLongitude());
paramsMap.put(“output”, “json”);
if(isSn) {
String paramsStr;
try {
paramsStr = toQueryString(paramsMap);
}catch (UnsupportedEncodingException e){
LogUtil.e(“error:”+e.getMessage());
return;
}
String wholeStr = new String(host + “?” + paramsStr + sk);
try {
wholeStr = URLEncoder.encode(wholeStr, “UTF-8”);
}catch (Exception e){
LogUtil.e(“error:”+e.getMessage());
return;
}
String sn = CommonUtil.MD5(wholeStr);
paramsMap.put(“sn”, sn);
}
task = new MyAsyncTask(Helper.toAppendUrl(paramsMap, UrlConstant.BAIDU_URL, host));
task.execute();
}
@Override
public void stop() {
if(paramsMap != null)
paramsMap.clear();
paramsMap = null;
task = null;
}
@Override
public void addReGeListener(IReGeListener listener) {
mListener = listener;
}
class MyAsyncTask extends AsyncTask<Void, Void, String>{
String mUrl;
public MyAsyncTask(String url) {
mUrl = url;
}
@Override
protected String doInBackground(Void… voids) {
return NetUtil.doHttpGet(mUrl);
}
@Override
protected void onPostExecute(String json) {
super.onPostExecute(json);
fromJson(json);
task = null;
}
}
/**
-
对Map内所有value作utf8编码,拼接返回结果
-
@param data
-
@return
-
@throws UnsupportedEncodingException
*/
private String toQueryString(Map<?, ?> data)
throws UnsupportedEncodingException {
StringBuffer queryString = new StringBuffer();
for (Map.Entry<?, ?> pair : data.entrySet()) {
queryString.append(pair.getKey() + “=”);
queryString.append(URLEncoder.encode((String) pair.getValue(),
“UTF-8”) + “&”);
}
if (queryString.length() > 0) {
queryString.deleteCharAt(queryString.length() - 1);
}
return queryString.toString();
}
/**
- 解析json
*/
private void fromJson(String json) {
LogUtil.e(“json:”+json);
if(json == null || json.isEmpty())
return;
if(mListener == null)
return;
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(json);
}catch (Exception e){
LogUtil.e(“error:” + e.getMessage());
return;
}
if(jsonObject.has(“status”)){
Integer state;
try {
state = (Integer) jsonObject.get(“status”);
// 0请求成功标志码
if(state != 0){
if(jsonObject.has(“message”))
mListener.onFail(state, jsonObject.getString(“message”));
return;
}
if(jsonObject.has(“result”)){
JSONObject obj;
JSONObject objAddress;
try{
obj = jsonObject.getJSONObject(“result”);
objAddress = obj.getJSONObject(“addressComponent”);
Latlng latlng = new Latlng();
latlng.setCountry(objAddress.getString(“country”));
latlng.setCountryCode(objAddress.getString(“country_code”));
latlng.setCity(objAddress.getString(“city”));
latlng.setSublocality(objAddress.getString(“district”));
latlng.setCityCode(obj.getInt(“cityCode”)+“”);
latlng.setAddress(objAddress.getString(“street”));
latlng.setName(obj.getString(“business”));
mListener.onSuccess(state, latlng);
}catch (Exception e){
LogUtil.e(“error:”+e.getMessage());
return;
}
}
}catch (Exception e){
LogUtil.e(“error:” + e.getMessage());
return;
}
}
}
}
反向地理编码:
/** 百度api返地理编码*/
public static final String BAIDU_URL = “https://api.map.baidu.com”;
/**特定经纬度的反向地理编码:*/
import android.content.Context;
import androidx.annotation.Nullable;
import com.mjzuo.location.bean.Latlng;
import com.mjzuo.location.constant.Constant;
import com.mjzuo.location.helper.GeReFactory;
import com.mjzuo.location.regelocation.IReGe;
import com.mjzuo.location.util.LogUtil;
lic class ReverseGeocodingManager {
IReGe mGeRe;
Context mContext;
public ReverseGeocodingManager(Context context) {
mContext = context;
mGeRe = GeReFactory.getReGeByType(Constant.GOOGLE_API);
mGeRe.init(mContext);
}
public ReverseGeocodingManager(Context context, @Nullable ReGeOption option) {
mContext = context;
mGeRe = GeReFactory.getReGeByType(option.getReGeType());
mGeRe.setOptions(option);
mGeRe.init(mContext);
}
public void reGeToAddress(@Nullable Latlng latlng) {
mGeRe.reGeToAddress(latlng);
}
public void stop() {
mGeRe.stop();
}
public void addReGeListener(@Nullable IReGe.IReGeListener listener) {
mGeRe.addReGeListener(listener);
}
public static class ReGeOption {
/**
-
api类型,默认谷歌服务
-
注意:个别机型内部移除了谷歌服务,如果不能请求,请切换别的api接口
*/
private int reGeType = Constant.GOOGLE_API;
/**
- 是否sn校验,默认签名校验方式,而非白名单方式
*/
private boolean isSn = true;
/**
- key
*/
private String key = “”;
/**
- sk
*/
private String sk = “”;
/**
- 是否打开log
*/
private boolean islog = true;
public int getReGeType() {
return reGeType;
}
public ReGeOption setReGeType(int reGeType) {
this.reGeType = reGeType;
return this;
}
public boolean isSn() {
return isSn;
}
public ReGeOption setSn(boolean sn) {
isSn = sn;
return this;
}
public boolean isIslog() {
return LogUtil.DEBUG;
}
public ReGeOption setIslog(boolean islog) {
LogUtil.DEBUG = islog;
return this;
}
public String getKey() {
return key;
}
public String getSk() {
return sk;
}
public ReGeOption setKey(String key) {
this.key = key;
return this;
}
public ReGeOption setSk(String sk) {
this.sk = sk;
return this;
}
}
}
LocationTaskActivity:
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.Manifest;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import com.mjzuo.location.GeocodingManager;
import com.mjzuo.location.bean.Latlng;
import com.mjzuo.location.constant.Constant;
import com.mjzuo.location.location.GoogleGeocoding;
import com.mjzuo.location.location.IGeocoding;
import com.mjzuo.location.regelocation.IReGe;
import com.mjzuo.location.ReverseGeocodingManager;
import java.util.List;
import pub.devrel.easypermissions.EasyPermissions;
public class LocationTaskActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks{
private static final String LOG_TAG = “tag_sl”;
/** 所要申请的权限*/
String[] perms = {
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.INTERNET,
Manifest.permission.READ_PHONE_STATE
};
/** 定位获取经纬度,包括LocationManager、基站地位*/
GeocodingManager siLoManager;
/** 反地理编码的manager,包括google反地理、百度反地理*/
ReverseGeocodingManager reGeManager;
TextView tvSimpleLo;
TextView tvSimpleAd;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_location_activity);
tvSimpleLo = findViewById(R.id.tv_simple_location_txt);
tvSimpleAd = findViewById(R.id.tv_simple_address_txt);
if (!EasyPermissions.hasPermissions(this, perms)) {
EasyPermissions.requestPermissions(this
, “必要的权限”
, 0
, perms);
}
ReverseGeocodingManager.ReGeOption reGeOption = new ReverseGeocodingManager.ReGeOption()
.setReGeType(Constant.BAIDU_API)// 百度api返地理编码
.setSn(true)// sn 签名校验方式
.setIslog(true);// 打印log
reGeManager = new ReverseGeocodingManager(this, reGeOption);
reGeManager.addReGeListener(new IReGe.IReGeListener() {
@Override
public void onSuccess(int state, Latlng latlng) {
Log.e(LOG_TAG,“reGeManager onSuccess:” + latlng);
tvSimpleAd.setText(“country:”+ latlng.getCountry()
-
“\n,city:” + latlng.getCity()
-
“\n,sublocality:” + latlng.getSublocality()
-
“\n,address:” + latlng.getAddress()
-
“\n,name:” + latlng.getName());
}
@Override
public void onFail(int errorCode, String error) {
Log.e(LOG_TAG,“error:” + error);
tvSimpleAd.setText(“errorCode:”+errorCode+“, error:” + error);
}
});
GeocodingManager.GeoOption option = new GeocodingManager.GeoOption()
.setGeoType(Constant.LM_API) // 使用openCellid服务器的基站地位
.setOption(new GoogleGeocoding.SiLoOption()
.setGpsFirst(true));// locationManager定位方式时,gps优先
siLoManager = new GeocodingManager(this, option);
siLoManager.start(new IGeocoding.ISiLoResponseListener() {
@Override
public void onSuccess(Latlng latlng) {
Log.e(LOG_TAG,“siLoManager onSuccess:” + latlng);
tvSimpleLo.setText(“latlng:” + latlng.getLatitude()
-
“\n,long:” + latlng.getLongitude()
-
“\n,provider:” + latlng.getProvider());
reGeManager.reGeToAddress(latlng);
}
@Override
public void onFail(String msg) {
Log.e(LOG_TAG,“error:” + msg);
tvSimpleAd.setText(“error:” + msg);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
if(siLoManager != null)
siLoManager.stop();
if(reGeManager != null){
reGeManager.stop();
}
}
@Override
public void onPermissionsGranted(int requestCode, @NonNull List perms) {
if(requestCode == 0 && siLoManager != null)
siLoManager.reStart();
}
@Override
public void onPermissionsDenied(int requestCode, @NonNull List perms) {
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// Forward results to EasyPermissions
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
}
请求用户权限
不开启GPS定位下的效果
开启定位服务
上地图查一下,结果十分的正确
检测到GPS未打开时间,让用户自行打开
最后
感谢您的阅读,在文末给大家准备一个福利。本人从事Android开发已经有十余年,算是一名资深的移动开发架构师了吧。根据我的观察发现,对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。
所以在此将我十年载,从萌新小白一步步成长为Android移动开发架构师的学习笔记,从Android四大组件到手写实现一个架构设计,我都有一一的对应笔记为你讲解。
当然我也为你们整理好了百度、阿里、腾讯、字节跳动等等互联网超级大厂的历年面试真题集锦。这也是我这些年来养成的习惯,一定要学会把好的东西,归纳整理,然后系统的消化吸收,这样才能极大的提高学习效率和成长进阶。碎片、零散化的东西,我觉得最没有价值的。就好比你给我一张扑克牌,我只会觉得它是一张废纸,但如果你给我一副扑克牌,它便有了它的价值。这和我们收集资料就要收集那些系统化的,是一个道理。
最后,赠与大家一句诗,共勉!
不驰于空想,不骛于虚声。不忘初心,方得始终。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!
FuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xvbmVseXdhdGVl,size_16,color_FFFFFF,t_70)
开启定位服务
上地图查一下,结果十分的正确
检测到GPS未打开时间,让用户自行打开
最后
感谢您的阅读,在文末给大家准备一个福利。本人从事Android开发已经有十余年,算是一名资深的移动开发架构师了吧。根据我的观察发现,对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。
所以在此将我十年载,从萌新小白一步步成长为Android移动开发架构师的学习笔记,从Android四大组件到手写实现一个架构设计,我都有一一的对应笔记为你讲解。
当然我也为你们整理好了百度、阿里、腾讯、字节跳动等等互联网超级大厂的历年面试真题集锦。这也是我这些年来养成的习惯,一定要学会把好的东西,归纳整理,然后系统的消化吸收,这样才能极大的提高学习效率和成长进阶。碎片、零散化的东西,我觉得最没有价值的。就好比你给我一张扑克牌,我只会觉得它是一张废纸,但如果你给我一副扑克牌,它便有了它的价值。这和我们收集资料就要收集那些系统化的,是一个道理。
[外链图片转存中…(img-h4QX53NH-1715104498914)]
最后,赠与大家一句诗,共勉!
不驰于空想,不骛于虚声。不忘初心,方得始终。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!