浅析Android地理定位(GPS)

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定位下的效果

在这里插入图片描述

开启定位服务

在这里插入图片描述

在这里插入图片描述

上地图查一下,结果十分的正确

在这里插入图片描述

补充


百度API使用方法官网链接

检测到GPS未打开时间,让用户自行打开

最后

感谢您的阅读,在文末给大家准备一个福利。本人从事Android开发已经有十余年,算是一名资深的移动开发架构师了吧。根据我的观察发现,对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。

所以在此将我十年载,从萌新小白一步步成长为Android移动开发架构师的学习笔记,从Android四大组件到手写实现一个架构设计,我都有一一的对应笔记为你讲解。

当然我也为你们整理好了百度、阿里、腾讯、字节跳动等等互联网超级大厂的历年面试真题集锦。这也是我这些年来养成的习惯,一定要学会把好的东西,归纳整理,然后系统的消化吸收,这样才能极大的提高学习效率和成长进阶。碎片、零散化的东西,我觉得最没有价值的。就好比你给我一张扑克牌,我只会觉得它是一张废纸,但如果你给我一副扑克牌,它便有了它的价值。这和我们收集资料就要收集那些系统化的,是一个道理。

最后,赠与大家一句诗,共勉!

不驰于空想,不骛于虚声。不忘初心,方得始终。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
FuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xvbmVseXdhdGVl,size_16,color_FFFFFF,t_70)

开启定位服务

在这里插入图片描述

在这里插入图片描述

上地图查一下,结果十分的正确

在这里插入图片描述

补充


百度API使用方法官网链接

检测到GPS未打开时间,让用户自行打开

最后

感谢您的阅读,在文末给大家准备一个福利。本人从事Android开发已经有十余年,算是一名资深的移动开发架构师了吧。根据我的观察发现,对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。

所以在此将我十年载,从萌新小白一步步成长为Android移动开发架构师的学习笔记,从Android四大组件到手写实现一个架构设计,我都有一一的对应笔记为你讲解。

当然我也为你们整理好了百度、阿里、腾讯、字节跳动等等互联网超级大厂的历年面试真题集锦。这也是我这些年来养成的习惯,一定要学会把好的东西,归纳整理,然后系统的消化吸收,这样才能极大的提高学习效率和成长进阶。碎片、零散化的东西,我觉得最没有价值的。就好比你给我一张扑克牌,我只会觉得它是一张废纸,但如果你给我一副扑克牌,它便有了它的价值。这和我们收集资料就要收集那些系统化的,是一个道理。

[外链图片转存中…(img-h4QX53NH-1715104498914)]

最后,赠与大家一句诗,共勉!

不驰于空想,不骛于虚声。不忘初心,方得始终。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 15
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值