Android LocationManager 获取经纬度和卫星信息

一、定位介绍

在不使用第三方地图SDK的情况下,也可以借助Android
本身的 location api 来实现获取地理位置相关信息功能,官方介绍见这里(需要翻墙):https://developer.android.com/reference/android/location/LocationManager

废话不多说,先看最终效果图:
在这里插入图片描述

二、代码

1、初始化LocationManager

         locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        if (!(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
                || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER))) {
            Toast.makeText(this, "请打开网络或GPS定位功能!", Toast.LENGTH_SHORT).show();
            Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            startActivityForResult(intent, 0);
            return;
        }

2、处理运行时权限

   if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(MainActivity.this,
                    new String[]{
                            Manifest.permission.ACCESS_COARSE_LOCATION,
                            Manifest.permission.ACCESS_FINE_LOCATION,
                            Manifest.permission.WRITE_EXTERNAL_STORAGE
                    }, 100);
        } else {
            initLocation();
        }

回调函数处理

  @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            // 相机权限
            case 100:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    //用户点击了同意授权
                    initLocation();
                } else {
                    //用户拒绝了授权
                    Toast.makeText(MainActivity.this, "权限被拒绝", Toast.LENGTH_SHORT).show();
                }
                break;
        }
    }

3、开始请求定位

优先获取gps定位结果,没有的话再获取网络定位结果,并添加2个listener

 		long minSecond = 2 * 1000;
 		long minDistance = 2;
       Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            if (location == null) {
                location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
            }
            updateLocation(location);

            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, minSecond, minDistance, listener);//LocationManager.GPS_PROVIDER

            mGPSStatusImpl = new GPSStatusImpl();
            locationManager.addGpsStatusListener(mGPSStatusImpl);

4、定位监听器

 public final LocationListener listener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            updateLocation(location);
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            switch (status) {
                // GPS状态为可见时
                case LocationProvider.AVAILABLE:
                    Log.i("xml", "当前GPS状态为可见状态");
                    break;
                // GPS状态为服务区外时
                case LocationProvider.OUT_OF_SERVICE:
                    Log.i("xml", "当前GPS状态为服务区外状态");
                    break;
                // GPS状态为暂停服务时
                case LocationProvider.TEMPORARILY_UNAVAILABLE:
                    Log.i("xml", "当前GPS状态为暂停服务状态");
                    break;
            }
        }

        @Override
        public void onProviderEnabled(String provider) {
  			@SuppressLint("MissingPermission")
            Location location = locationManager.getLastKnownLocation(provider);
            updateLocation(location);
        }

        @Override
        public void onProviderDisabled(String provider) {
        }
    };

5、卫星监听器

在requestLocationUpdates方法后add监听器,在onDestroy或者onStop方法中remove该监听器

private class GPSStatusImpl implements GpsStatus.Listener
    {
        @Override
        public void onGpsStatusChanged(int event)
        {
            switch (event)
            {
                case GpsStatus.GPS_EVENT_FIRST_FIX:  //第一次定位
                    break;

                case GpsStatus.GPS_EVENT_SATELLITE_STATUS:  //卫星状态改变
                {
                    //获取当前状态
                    @SuppressLint("MissingPermission")
                    GpsStatus gpsStatus = locationManager.getGpsStatus(null);
                    //获取卫星颗数的默认最大值
                    int maxSatellites = gpsStatus.getMaxSatellites();
                    //创建一个迭代器保存所有卫星
                    Iterator<GpsSatellite> iters = gpsStatus.getSatellites().iterator();
                    int count = 0;
                    while (iters.hasNext() && count <= maxSatellites)
                    {
                        GpsSatellite s = iters.next();
                        // 只有信噪比不为0时才算合格的卫星
                        if (s.getSnr() != 0) {
                            count++;
                        }
                    }

                    stars = count;
			  		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String curTime = dateFormat.format(new Date());
                    System.out.println(curTime + "-----卫星数量nun----" + stars);
                    textView2.setText("实时卫星数量:" + stars);
                    break;
                }

                case GpsStatus.GPS_EVENT_STARTED:   //定位启动
                    break;

                case GpsStatus.GPS_EVENT_STOPPED:   //定位结束
                    break;
            }
        }
    }

6、更新定位

关键核心代码,把结果展示在textview并写入本地文件中

private void updateLocation(Location location) {
        String result;
        double lat;
        double lon;

        if (location != null) {
            lat = location.getLatitude();
            lon = location.getLongitude();
            if (location.hasSpeed()) {
                speed = location.getSpeed() * 3.6;
            } else {
                if( lastLocation != null) {
                    speed = getMySpeed(lastLocation, location);
                }
            }

            result = "纬度:" + lat + "\n经度:" + lon + "\n速度:" + String.format("%.2f", speed) + " km/h\n卫星数量:" + stars;
            Log.i("xml", "显示结果 = " +  result);
            lastLocation = location;
        } else {
            result = "无法获取经纬度信息";
        }

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat dateFormatDate = new SimpleDateFormat("yyyyMMdd");
        String curTime = dateFormat.format(new Date());
        String curDate = dateFormatDate.format(new Date());

        // 把结果展示在界面上
        textView.setText(curTime + "\n" + result);

        // 把结果写入文件
        Utils.writeFileAppend(Utils.BASE_PROJECT_IMAGE_PATH + "log_" + curDate + ".txt", curTime + "\n" + result.replace("\n", " "));
    }

三、遇到的坑

使用LocationManager需要注意以下几个点:
(1)在开启网络定位的前提下,经过测试,如果只根据时间来定位的话,发现允许的最短时间是20秒,代码中设置低于这个时间的话,还是会以20秒作为定位间隔,与此同时,最小距离还必须设置为0,如果非0的话监听器就无法再被回调来获取网络定位经纬度。
(2)获取卫星数量时(简称搜星),尽量要在户外空旷的地方,同时搜星一般比较慢,而且代码中要实现GpsStatus.Listener接口,不然数量可能为0,同时要添加信噪比判断,不然容易获取较多的卫星数量
(3)在Manifest添加了相关权限并且代码中已经做了运行时权限处理代码,主要是以下两个权限:

 Manifest.permission.ACCESS_COARSE_LOCATION
 Manifest.permission.ACCESS_FINE_LOCATION

如果requestLocationUpdates这个方法还是报红的话,那么只有添加注解来解决了

 @SuppressLint("MissingPermission")

(4)在获取gps速度的时候,getSpeed方法要乘以3.6,这是为了把单位米每秒转换成千米每小时
(5)由于网络定位误差较大,建议只开启GPS定位,当hasSpeed为false的时候,使用两个经纬度之差和时间之差来获取实时速度

四、Demo下载

下载地址见这里,https://download.csdn.net/download/diyangxia/11219445

猜你喜欢

转载自blog.csdn.net/diyangxia/article/details/90674393
今日推荐