Android 原生定位开发(解决个别手机定位失败问题)


文章目录


前言

在android开发中地图和定位是很多软件不可或缺的内容,这些特色功能也给人们带来了很多方便。定位一般分为三种发方案:即GPS定位、Google网络定位以及基站定位。


本文分别介绍GPS定位、以及基于Google的网络Wifi定位的详细步骤,(小米手机获取位置信息locationManager.getLastKnownLocation(provider)的Location一直为空,查了资料换了种获取手机getProviders的方式就可以了)

一、实现步骤

一般来说我们实现原生定位的流程大概是:先判断有无权限》有权限启动一个LocationSrevice去获取定位》最后携带所需的定位信息返回,进行开发。

二、使用步骤

1.服务启动工具类

代码如下(示例):大概步骤如下,权限请求可自定义开发关键的是LocationService

java 复制代码
/**
 * 获取定位
 */
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" />

2.实现LocationService

代码如下(示例):

java 复制代码
/**
 * 获取定位服务
 */
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) {
        }

    }

    @SuppressLint("MissingPermission")
    private Location getLastKnownLocation(LocationManager locationManager) {
        List<String> providers = locationManager.getProviders(true);
        Location bestLocation = null;
        for (String provider : providers) {
            Location l = locationManager.getLastKnownLocation(provider);
            if (l == null) {
                continue;
            }
            if (bestLocation == null || l.getAccuracy() < bestLocation.getAccuracy()) {
                bestLocation = l;
            }
        }
        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原生获取定位内容,本文详细展现了完整流程,希望对大家会有帮助,公司如果有实力大可不必如此,直接给第三方地图交钱就好了,毕竟人家又快又准(本文仅仅适用于只需经纬度或者地址信息的同学,有地图展现需求的只能想别的方法了哈哈)。

相关推荐
阿巴斯甜2 天前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker2 天前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq95272 天前
Andorid Google 登录接入文档
android
黄林晴2 天前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab2 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿2 天前
Android MediaPlayer 笔记
android
Jony_2 天前
Android 启动优化方案
android
阿巴斯甜2 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇2 天前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_3 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android