使用Android GPS api 实现一个轨迹记录的小功能

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/Achilles_Lee/article/details/78337083

引入

  • 市场上的跑步软件已经是非常多了,如咕咚和悦跑圈还有其他,很多大厂也在涉足这个方面。而最简单的运动跑步,最近几年也因简单,不限场地,运动效果出众备受大众喜欢。
  • 我的这篇文章的内容很多也是从网上学习其他的博客内容,外加利用android自身的提供的api实现的,希望能对有这方面需求的朋友有所帮助。
  • 项目地址:https://github.com/Lilee902/RunGps

介绍

  • 先上两张图,界面比较丑,不过一些数据基本都有了,这个图片是临时要用截取的,所以轨迹线很短,之前有实际测过,轨迹线OK的。
  • 因为demo是很久之前写的,我的测试手机是5.1的系统,当时并没有做运行时权限判定,如果您的测试环境是在6.0+的话,请注意加上权限判断。
  • 经纬度点的获取是利用android的api LocationManager以及相关的类实现的。
  • 获取到经纬度点展示时使用的百度地图的com.baidu.mapapi.map.MapView这个类做的页面显示(百度地图只做页面显示使用)。
  • 另外,android api 获取到的点是谷歌坐标,需要用百度sdk中的api转化为百度的坐标,然后再做显示,不然位置会整体发生偏移。(火星坐标百度百科 介绍:https://baike.baidu.com/item/%E7%81%AB%E6%98%9F%E5%9D%90%E6%A0%87%E7%B3%BB%E7%BB%9F ,具体介绍,网上也有很多文章)。

主要代码介绍

  • API 获取经纬度点,不过这样直接获取location,经常获取到的为null,因为这个时候,gps还没有定位成功。
        if (locationManager == null) {
            locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        }

        Location location = mActPersenter.getLatLng(locationManager);
        if (location != null) {
            firstGetLocation(location);
        }
  • 大家自然会想到,不能直接获取,那就加listener,三板斧嘛,当然是有加监听的,如下代码,其中 LocationManager.GPS_PROVIDER,LocationManager.NETWORK_PROVIDER 分别为利用手机gps和利用蜂窝网络获取。这里要使用gps,因为蜂窝网络会发生漂移。(如果有朋友只是定位大体位置的话,可以用network,这个效率和速度都会更快)

     private LocationManager locationManager;
         private void initListener() {
    
        if (locationManager == null) {
            locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        }
    
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
         1000, 1,locationGpsListener);
    }
  • 那么,这个locationGpsListener里面具体要做什么,下面这段代码已经可以基本解答你的疑惑了。

    /**
     * location的监听。
     */
    private MLocationListener locationGpsListener = new MLocationListener() {
    
        // 当坐标改变时触发此函数,如果Provider传进相同的坐标,它就不会被触发
        @Override
        public void onLocationChanged(Location mlocation) {
            if (mlocation != null) {
                if (!isPause) {// 如果没有暂停,则记录数据。
                    if (mMoveGpsDataList != null && mMoveGpsDataList.size() >= 1) {
    
                        speed = mlocation.getSpeed();
                        double latitude = mlocation.getLatitude();
                        double longitude = mlocation.getLongitude();
                        LatLng latLng = new LatLng(latitude, longitude);
                        Logger.e(LTAG, "B_latLng : " + latLng.latitude + "," + latLng.longitude);
                        //google坐标转百度坐标。
                        latLng = gpsToBaidu(latLng);
    
                        PositionBean lastPosition = mMoveGpsDataList.getLast();
                        // 如果位置和上一次记录的位置点相同,则认为没有移动。
                        if (lastPosition.latlng.latitude != latLng.latitude
                                || lastPosition.latlng.longitude != latLng.longitude) {
                            // 计算移动距离,和速度。
                            PositionBean oncePosition = getMoveGpsData(lastPosition, latLng);
                            if (oncePosition == null) {
                                showToast("点漂移了一次!");
                            } else {
                                mPointListWithGps.add(latLng);
                                mMoveGpsDataList.add(oncePosition);
                                mListGpsLocationAdapter.update(mMoveGpsDataList);
                                updateListenerView();
                            }
                        } else {
                            Logger.e(LTAG, "未移动,LocationSpeed : " + speed);
                            if (onces % 10 == 0) {
                                showToast("未移动,LocationSpeed : " + speed);
                                onces = 0;
                            }
                            onces++;
                        }
                    } else {
                        firstGetLocation(mlocation);
                    }
    
                } else {// 如果暂停了,则toast提示。
                    showToast("位置改变了一次,暂停状态未记录!");
                }
            }
        }
    
    };
  • 你可能也注意到了,里面有个方法,gpsToBaidu(latLng);这个是应该就是坐标转换的了,具体的实现如下:
    /**
     * 标准的GPS经纬度坐标直接在地图上绘制会有偏移,这是测绘局和地图商设置的加密,要转换成百度地图坐标
     *
     * @return 百度地图坐标
     */
    public LatLng gpsToBaidu(LatLng data) {// data格式 nmea标准数据 ddmm.mmmmm,ddmm.mmmm
                                           // 如3030.90909,11449.1234

        // 将GPS设备采集的原始GPS坐标转换成百度坐标
        CoordinateConverter converter = new CoordinateConverter();
        converter.from(CoordType.GPS);
        // sourceLatLng待转换坐标
        converter.coord(data);
        LatLng desLatLng = converter.convert();
        return desLatLng;
    }
  • 到这里,好像就介绍的差不多了。只剩下最后一步展示了,这个时候就要用到百度sdk了,当然上面坐标转换也是用百度的,不过也是为这一步做准备的。
private void updateListenerView() {
        if (mMoveGpsDataList != null && mMoveGpsDataList.size() >= 1) {
            PositionBean positionBean = mMoveGpsDataList.getLast();
            mTvDis.setText("距离 : " + mTotalDistance);
            mTvV.setText("配速 : " + positionBean.velocity + "m/s");
            mTvTimes.setText("时间 : " + getFormatTime(mTotalTimes));
            if (mPointListWithGps != null && mPointListWithGps.size() > 1) {
                mBaiduMap.clear();// 先将地图上的点清除。
                // 在地图上画线。
                OverlayOptions polylineOption = new PolylineOptions().points(mPointListWithGps)
                        .width(10).color(Color.RED);
                Polyline mVirtureRoad = (Polyline) mBaiduMap.addOverlay(polylineOption);
                // 在地图上画起始点。
                OverlayOptions markerOptions;
                markerOptions = new MarkerOptions().flat(true).anchor(0.5f, 0.5f)
                        .icon(BitmapDescriptorFactory.fromResource(R.mipmap.icon_positioning_big))
                        .position(mPointListWithGps.get(0));
                Marker mMoveMarker = (Marker) mBaiduMap.addOverlay(markerOptions);
            }

            // 设置当前位置的蓝色的点。
            LatLng latLng = positionBean.latlng;
            if (latLng != null) {
                MyLocationData locData = new MyLocationData.Builder().accuracy(40)
                        // 此处设置开发者获取到的方向信息,顺时针0-360
                        .direction(100).latitude(latLng.latitude).longitude(latLng.longitude)
                        .build();
                mBaiduMap.setMyLocationData(locData);
            }
        }

    }

结束

用android api 实现跑步基本内容几乎都在这里了。demo中也有一些计算速度距离之类的数据。已经有了经纬度点和每个点之间的时间间隔,相信这些已经就不是什么问题了,都是一些计算。根据需求来就可以了。
最后,谢谢大家,希望可以帮到大家,demo不完善,见谅。后期我可能会完善一下。如果错误,望不吝斧正,谢谢。

猜你喜欢

转载自blog.csdn.net/Achilles_Lee/article/details/78337083