赞
踩
在android开发中地图和定位是很多软件不可或缺的内容,这些特色功能也给人们带来了很多方便。定位一般分为三种发方案:即GPS定位、Google网络定位以及基站定位。
本文分别介绍GPS定位、以及基于Google的网络Wifi定位的详细步骤,(小米手机获取位置信息locationManager.getLastKnownLocation(provider)的Location一直为空,查了资料换了种获取手机getProviders的方式就可以了)
一般来说我们实现原生定位的流程大概是:先判断有无权限》有权限启动一个LocationSrevice去获取定位》最后携带所需的定位信息返回,进行开发。
代码如下(示例):大概步骤如下,权限请求可自定义开发关键的是LocationService
/** * 获取定位 */ public class MyLocationManager implements LocationService.LocationCallBack { private Activity context; private OnLocationListener onLocationListener; private String[] stringsLocation = new String[]{Permission.ACCESS_FINE_LOCATION, Permission.ACCESS_COARSE_LOCATION}; @Override public void Location_Return(double Location_latitude, double Location_longitude, String province, String city, String area, String featureName) { onLocationListener.OnLocation(Location_latitude, Location_longitude, province, city, area, featureName); } public interface OnLocationListener { void OnLocation(double Location_latitude, double Location_longitude, String province, String city, String area, String featureName); } public void setOnLocationListener(OnLocationListener onLocationListener) { this.onLocationListener = onLocationListener; } public MyLocationManager(@NonNull Activity context) { this.context = context; if (!XXPermissions.isGranted(context, stringsLocation)) { MessageDialog codeDialog = new MessageDialog(context, "位置信息权限使用说明", "为确保你能在******内使用位置信息******,******需要获取你的位置信息权限。允许后,你可以随时通过手机系统设置对授权进行管理。", "取消", "去授权"); codeDialog.setCancelable(false); codeDialog.show(); codeDialog.setOnSumbitTextCodeListener(() -> { doMainPermission(); codeDialog.dismiss(); }); codeDialog.setOnCancelListener(() -> { codeDialog.dismiss(); }); } else { initData(); } } private void doMainPermission() { XXPermissions.with(context).permission(stringsLocation).request(new OnPermissionCallback() { @Override public void onGranted(@NonNull List<String> permissions, boolean allGranted) { if (allGranted) { initData(); } } @Override public void onDenied(@NonNull List<String> permissions, boolean doNotAskAgain) { if (doNotAskAgain) { } } }); } @SuppressLint("MissingPermission") private void initData() { // 创建 Service 实例 LocationService myService = new LocationService(); // 设置回调接口 myService.setCallback(this); // 启动 Service 并执行操作 Intent serviceIntent = new Intent(context, LocationService.class); context.startService(serviceIntent); } } /**-------------------------/ 不要忘了注册 <service android:name=".utils.LocationService" android:enabled="true" android:exported="false" />
代码如下(示例):
/** * 获取定位服务 */ public class LocationService extends Service { private LocationManager locationManager; private MyLocationListener myLocationListener; public static LocationCallBack mCallBack = null; public interface LocationCallBack { void Location_Return(double Location_latitude, double Location_longitude, String province, String city, String area, String featureName); } public void setCallback(LocationCallBack callback) { this.mCallBack = callback; } @Override public IBinder onBind(Intent intent) { return null; } @SuppressLint("MissingPermission") @Override public void onCreate() { super.onCreate(); myLocationListener = new MyLocationListener(); locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); try { GPSLocation(); } catch (Exception e) { if (ObjectUtils.isNotEmpty(locationManager) && ObjectUtils.isNotEmpty(myLocationListener)) locationManager.removeUpdates(myLocationListener); // 停止所有的定位服务 stopSelf(); // 获取到经纬度以后,停止该service } } class MyLocationListener implements LocationListener { // 位置改变时获取经纬度 @Override public void onLocationChanged(Location location) { if (ObjectUtils.isNotEmpty(location)) { toGeocoder(location); } } // 状态改变时 @Override public void onStatusChanged(String provider, int status, Bundle extras) { } // 提供者可以使用时 @Override public void onProviderEnabled(String provider) { } // 提供者不可以使用时 @Override public void onProviderDisabled(String provider) { } } /* **系统内容提供器介绍 **一共为四种方式"passive","network","fused","gps" ** "gps":GPS_PROVIDER(GNSS) GNSS HAL 接口和芯片打交道 ** "network":NETWORK_PROVIDER 依赖设备厂商的具体实现,Android 默认实现依赖 Google 提供的 GMS ** 实现国内无法使用;一般厂商会实现为通过基站 / WIFI / 蓝牙进行融合定位 ** "fused":调用 GMS(谷歌移动服务) 进行定位,国内用不了 ** "passive":使用 PassiveProvider 在系统位置更新时通知给应用,分享其他 PROVIDER 的定位结果 */ @SuppressLint("MissingPermission") private Location getLastKnownLocation(LocationManager locationManager) { Location bestLocation = null; List<String> providers = locationManager.getProviders(true); //由于国内用不了fused 剔除他 if (providers.contains("fused")) providers.remove("fused"); //这里我们按照首字母排序,使内容提供者调用顺序为gps network passive Collections.sort(providers); LogUtils.e("provider:" + GsonUtils.toJson(providers)); for (String provider : providers) { Location location = locationManager.getLastKnownLocation(provider); if (ObjectUtils.isEmpty(location)) { LogUtils.e(provider + "定位服务不可用"); //执行下一个 continue; } else { bestLocation = location; LogUtils.e(provider + "定位服务成功"); //定位成功返回 break; } } return bestLocation; } @SuppressLint("MissingPermission") private void GPSLocation() { Location location = getLastKnownLocation(locationManager); if (location != null) { //不为空,显示地理位置经纬度 String longitude = "Longitude:" + location.getLongitude(); String latitude = "Latitude:" + location.getLatitude(); LogUtils.e("Location:" + longitude + latitude); toGeocoder(location); } else { LogUtils.e("Location:" + "Location为空"); if (ObjectUtils.isNotEmpty(locationManager) && ObjectUtils.isNotEmpty(myLocationListener)) locationManager.removeUpdates(myLocationListener); // 停止所有的定位服务 stopSelf(); // 获取到经纬度以后,停止该service } } @SuppressLint("MissingPermission") private void toGeocoder(Location location) { String province = ""; String city = ""; String area = ""; String featureName = ""; try { Geocoder geocoder = new Geocoder(getApplicationContext(), Locale.getDefault()); List<Address> addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1); if (ObjectUtils.isNotEmpty(addresses) && 0 < addresses.size()) { Address address = addresses.get(0); if (ObjectUtils.isNotEmpty(address)) { // 获取省份(province) province = address.getAdminArea(); // 获取城市(City) city = address.getLocality(); // 获取区县(area) area = address.getSubLocality(); // 获取详细地址 featureName = address.getFeatureName(); // 获取街道地址 String addressLine = address.getAddressLine(0); // 打印详细地址信息 LogUtils.e("AddressInfo", "province: " + province); LogUtils.e("AddressInfo", "City: " + city); LogUtils.e("AddressInfo", "area: " + area); LogUtils.e("AddressInfo", "FeatureName: " + featureName); LogUtils.e("AddressInfo", "Address Line: " + addressLine); } mCallBack.Location_Return(location.getLatitude(), location.getLongitude(), province, city, area, featureName); } if (ObjectUtils.isNotEmpty(locationManager) && ObjectUtils.isNotEmpty(myLocationListener)) locationManager.removeUpdates(myLocationListener); // 停止所有的定位服务 stopSelf(); // 获取到经纬度以后,停止该service } catch (Exception e) { if (ObjectUtils.isNotEmpty(locationManager) && ObjectUtils.isNotEmpty(myLocationListener)) locationManager.removeUpdates(myLocationListener); // 停止所有的定位服务 stopSelf(); // 获取到经纬度以后,停止该service e.printStackTrace(); } } @SuppressLint("MissingPermission") @Override public void onDestroy() { super.onDestroy(); if (ObjectUtils.isNotEmpty(locationManager) && ObjectUtils.isNotEmpty(myLocationListener)) locationManager.removeUpdates(myLocationListener); // 停止所有的定位服务 stopSelf(); } }
该处使用原生定位获取经纬度、省市县等数据的详细步骤。
以上就是今天要讲的使用Android原生获取定位内容,本文详细展现了完整流程,希望对大家会有帮助,公司如果有实力大可不必如此,直接给第三方地图交钱就好了,毕竟人家又快又准(本文仅仅适用于只需经纬度或者地址信息的同学,有地图展现需求的只能想别的方法了哈哈)。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。