Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >腾讯位置服务GPS轨迹回放-安卓篇

腾讯位置服务GPS轨迹回放-安卓篇

原创
作者头像
腾讯位置服务
发布于 2021-06-04 06:50:53
发布于 2021-06-04 06:50:53
2.3K0
举报
文章被收录于专栏:腾讯位置服务腾讯位置服务

前言

当我们使用地图进行开发时,利用已经录制好的轨迹进行轨迹回放来检查导航的准确性是十分常用的手段,并且上一篇已经讲完了关于地图使用时GPS轨迹文件的录制,现在对于安卓系统下使用腾讯导航SDK进行轨迹回放做一个分享

前期准备

腾讯导航SDK依赖于腾讯地图SDK、腾讯定位SDK,具体权限的开通需要去lbs.qq.com 的官网控制台去操作,另外导航SDK的权限可以联系小助手咨询(如下图所示),这里就不多做探讨

16222560693250.jpg
16222560693250.jpg

轨迹回放正片

系统架构

16224265311888.jpg
16224265311888.jpg

GPS回放系统分成两部分:GPSPlaybackActivity 和 GPSPlaybackEngine。

GPSPlayback负责和外界的交互,主要是信息的传递和导航SDK的交互,而GPSPlaybackEngine负责具体的读取文件和将定位点通过多线程runnable机制灌入listener。

开始轨迹回放

BaseNaviActivity.java

baseNaviActivity 主要是对于导航SDK naviView部分的生命周期的管理,必须实现,否则不能进行导航!

代码语言:txt
AI代码解释
复制
/**
 * 导航 SDK {@link CarNaviView} 初始化与周期管理类。
 */
public abstract class BaseNaviActivity {

    private static Context mApplicationContext;

    protected CarNaviView mCarNaviView;

    // 建立了TencentCarNaviManager 单例模式,也可以直接调用TencentCarNaviManager来建立自己的carNaviManager
    public static final Singleton<TencentCarNaviManager> mCarManagerSingleton =
            new Singleton<TencentCarNaviManager>() {
                @Override
                protected TencentCarNaviManager create() {
                    return new TencentCarNaviManager(mApplicationContext);
                }
            };

    public static TencentCarNaviManager getCarNaviManager(Context appContext) {
        mApplicationContext = appContext;
        return mCarManagerSingleton.get();
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutID());
        super.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        mApplicationContext = getApplicationContext();
        mCarNaviView = findViewById(R.id.tnk_car_navi_view);
        mCarManagerSingleton.get().addNaviView(mCarNaviView);
    }

    public int getLayoutID() {
        return R.layout.tnk_activity_navi_base;
    }

    protected View getCarNaviViewChaild() {
        final int count = mCarNaviView.getChildCount();
        if (0 >= count) {
            return mCarNaviView;
        }
        return mCarNaviView.getChildAt(count - 1);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (!isDestoryMap()) {
            return;
        }
        mCarManagerSingleton.get().removeAllNaviViews();
        if (mCarNaviView != null) {
            mCarNaviView.onDestroy();
        }
//        mCarManagerSingleton.destory();
    }

    @Override
    protected void onStart() {
        super.onStart();
        if (mCarNaviView != null) {
            mCarNaviView.onStart();
        }
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        if (mCarNaviView != null) {
            mCarNaviView.onRestart();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mCarNaviView != null) {
            mCarNaviView.onResume();
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mCarNaviView != null) {
            mCarNaviView.onPause();
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mCarNaviView != null) {
            mCarNaviView.onStop();
        }
    }

    protected boolean isDestoryMap() {
        return true;
    }
}
GPSPlaybackActivity.java

这一部分主要是对于导航 SDK的交互和添加导航UI部分初始化工作。注意导航sdk一定要先算路,再开始导航。算路可以取得GPS文件的首行为起点,末行为终点。

用到的fields

代码语言:txt
AI代码解释
复制
    private static final String LOG_TAG = "[GpsPlayback]";

    // gps 文件路径
    private String mGpsTrackPath;
    // gps 轨迹的起终点
    private NaviPoi mFrom, mTo;

    // 是否是84坐标系
    private boolean isLocation84 = true;

因为在GPSPlaybackEngine已经进行了listener监听,所以需要对于导航SDK进行灌点

代码语言:txt
AI代码解释
复制
// 腾讯定位sdk的listener
    private TencentLocationListener listener = new TencentLocationListener() {
        @Override
        public void onLocationChanged(TencentLocation tencentLocation, int error, String reason) {
            if (error != TencentLocation.ERROR_OK || tencentLocation == null) {
                return;
            }
            Log.d(LOG_TAG, "onLocationChanged : "
                    + ", latitude" + tencentLocation.getLatitude()
                    + ", longitude: " + tencentLocation.getLongitude()
                    + ", provider: " + tencentLocation.getProvider()
                    + ", accuracy: " + tencentLocation.getAccuracy());

            // 将定位点灌入导航SDK
            // mCarManagerSingleton是使用导航SDK的carNaviManager创建的单例,开发者可以自己实现
            mCarManagerSingleton.get().updateLocation(ConvertHelper
                    .convertToGpsLocation(tencentLocation), error, reason);
        }

        @Override
        public void onStatusUpdate(String provider, int status, String description) {
            Log.d(LOG_TAG, "onStatusUpdate provider: " + provider
                    + ", status: " + status
                    + ", desc: " + description);

            // 更新GPS状态.
            mCarManagerSingleton.get().updateGpsStatus(provider, status, description);
        }
    };

onCreate方法初始化UI和添加callback

代码语言:txt
AI代码解释
复制
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 获取GPS文件轨迹路径,这里可以由开发者自己获取
        mGpsTrackPath = getIntent().getStringExtra("gpsTrackPath");
        if (mGpsTrackPath == null || mGpsTrackPath.isEmpty()) {
            return;
        }

        initUi();
        addTencentCallback();

        new Handler().post(() -> {
        
            // 目的获取每条轨迹的arraylist
            ArrayList<String> gpsLineStrs = readGpsFile(mGpsTrackPath);
            if (gpsLineStrs == null || gpsLineStrs.isEmpty()) {
                return;
            }
            // 获取起终点
            getFromAndTo(gpsLineStrs);
            if (mFrom == null || mTo == null) {
                return;
            }
            final Handler handlerUi = new Handler(Looper.getMainLooper());
            handlerUi.post(() -> searchAndStartNavigation());
        });

    }
    

private void initUi() {
        mCarManagerSingleton.get().setInternalTtsEnabled(true);

        final int margin = CommonUtils.dip2px(this, 36);
        // 全览模式的路线边距
        mCarNaviView.setVisibleRegionMargin(margin, margin, margin, margin);
        mCarNaviView.setAutoScaleEnabled(true);
        mCarManagerSingleton.get().setMulteRoutes(true);
        mCarNaviView.setNaviMapActionCallback(mCarManagerSingleton.get());

        // 使用默认UI
        CarNaviInfoPanel carNaviInfoPanel = mCarNaviView.showNaviInfoPanel();
        carNaviInfoPanel.setOnNaviInfoListener(() -> {
            mCarManagerSingleton.get().stopNavi();
            finish();
        });
        CarNaviInfoPanel.NaviInfoPanelConfig config = new CarNaviInfoPanel.NaviInfoPanelConfig();
        config.setRerouteViewEnable(true);             // 重算按钮
        carNaviInfoPanel.setNaviInfoPanelConfig(config);
    }

    private void addTencentCallback() {
        mCarManagerSingleton.get().addTencentNaviCallback(mTencentCallback);
    }
    
    private TencentNaviCallback mTencentCallback = new TencentNaviCallback() {
        @Override
        public void onStartNavi() { }

        @Override
        public void onStopNavi() { }

        @Override
        public void onOffRoute() { }

        @Override
        public void onRecalculateRouteSuccess(int recalculateType,
                                              ArrayList<RouteData> routeDataList) { }
        @Override
        public void onRecalculateRouteSuccessInFence(int recalculateType) { }

        @Override
        public void onRecalculateRouteFailure(int recalculateType,
                                              int errorCode, String errorMessage) { }

        @Override
        public void onRecalculateRouteStarted(int recalculateType) { }

        @Override
        public void onRecalculateRouteCanceled() { }

        @Override
        public int onVoiceBroadcast(NaviTts tts) {
            return 0;
        }

        @Override
        public void onArrivedDestination() { }

        @Override
        public void onPassedWayPoint(int passPointIndex) { }

        @Override
        public void onUpdateRoadType(int roadType) { }

        @Override
        public void onUpdateParallelRoadStatus(ParallelRoadStatus parallelRoadStatus) {

        }

        @Override
        public void onUpdateAttachedLocation(AttachedLocation location) { }

        @Override
        public void onFollowRouteClick(String routeId, ArrayList<LatLng> latLngArrayList) { }
    };

readGpsFile方法

代码语言:txt
AI代码解释
复制
private ArrayList<String> readGpsFile(String fileName) {
        ArrayList<String> gpsLineStrs = new ArrayList<>();
        BufferedReader reader = null;
        try {
            File file = new File(fileName);
            InputStream is = new FileInputStream(file);
            reader = new BufferedReader(new InputStreamReader(is));

            String line;
            while ((line = reader.readLine()) != null) {
                gpsLineStrs.add(line);
            }
            return gpsLineStrs;
        } catch (Exception e) {
            Log.e(LOG_TAG, "startMockTencentLocation Exception", e);
            e.printStackTrace();
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (Exception e) {
                Log.e(LOG_TAG, "startMockTencentLocation Exception", e);
                e.printStackTrace();
            }
        }
        return null;
    }

getFromAndTo方法,获取起终点为进行算路

代码语言:txt
AI代码解释
复制
    private void getFromAndTo(ArrayList<String> gpsLineStrs) {
        final int size;
        if ((size = gpsLineStrs.size()) < 2) {
            return;
        }
        final String firstLine = gpsLineStrs.get(0);
        final String endLine = gpsLineStrs.get(size - 1);
        try {
            final String[] fromParts = firstLine.split(",");
            mFrom = new NaviPoi(Double.valueOf(fromParts[1]), Double.valueOf(fromParts[0]));
            final String[] endParts = endLine.split(",");
            mTo = new NaviPoi(Double.valueOf(endParts[1]), Double.valueOf(endParts[0]));
        } catch (Exception e) {
            mFrom = null;
            mTo = null;
        }
    }

算路searchAndStartNavigation()

代码语言:txt
AI代码解释
复制
可以使用导航SDK的算路方法并且获取算路成功和失败的回调


    private void searchAndStartNavigation() {
        mCarManagerSingleton.get()
                .searchRoute(new TencentRouteSearchCallback() {
                    @Override
                    public void onRouteSearchFailure(int i, String s) {
                        toast("路线规划失败");
                    }

                    @Override
                    public void onRouteSearchSuccess(ArrayList<RouteData> arrayList) {
                        if (arrayList == null || arrayList.isEmpty()) {
                            toast("未能召回路线");
                            return;
                        }
                        handleGpsPlayback();
                    }
                });
    }
    

调用GpsPlaybackEngine方法,进行listen定位,然后开始导航

代码语言:txt
AI代码解释
复制
    private void handleGpsPlayback() {

// 与GpsPlaybackEngine 进行交互, 添加locationListener
GpsPlaybackEngine.getInstance().addTencentLocationListener(listener);

//与GpsPlaybackEngine 进行交互,开始定位
        GpsPlaybackEngine.getInstance().startMockTencentLocation(mGpsTrackPath, isLocation84);
        try {
            mCarManagerSingleton.get().startNavi(0);
        } catch (Exception e) {
            toast(e.getMessage());
        }
    }

结束导航

代码语言:txt
AI代码解释
复制
    @Override
    protected void onDestroy() {
// 与GpsPlaybackEngine 进行交互, removelocationListener
mCarManagerSingleton.get().removeTencentNaviCallback(mTencentCallback);
//与GpsPlaybackEngine 进行交互,结束定位GpsPlaybackEngine.getInstance().removeTencentLocationListener(listener);
        GpsPlaybackEngine.getInstance().stopMockLocation();
        if (mCarManagerSingleton.get().isNavigating()) {
        // 结束导航
            mCarManagerSingleton.get().stopNavi();
        }
        super.onDestroy();
    }
GPSPlaybackEngine.java

这一部分主要是对于GPS文件进行读取并且提供外界可用的add/removelistener方法,start/stopMockLocation方法

因为要让engine运行在自己的线程,所以使用runnable机制

代码语言:txt
AI代码解释
复制
public class GpsPlaybackEngine implements Runnable{

            // 代码在下方
}

而使用到的fields

代码语言:txt
AI代码解释
复制
// Tencent轨迹Mock, TencentLocationListener需要利用腾讯定位SDK获取
private ArrayList<TencentLocationListener> mTencentLocationListeners = new ArrayList<>();
    
// 获取的location数据
private List<String> mDatas = new ArrayList<String>();
     
private boolean mIsReplaying = false;

private boolean mIsMockTencentLocation = true;

private Thread mMockGpsProviderTask = null;

// 是否已经暂停
private boolean mPause = false;

private double lastPointTime = 0;
private double sleepTime = 0;

关键方法

  • listener相关
代码语言:txt
AI代码解释
复制
    // 添加listener
    public void addTencentLocationListener(TencentLocationListener listener) {
        if (listener != null) {
            mTencentLocationListeners.add(listener);
        }
    }

    // 移除listener 
    public void removeTencentLocationListener(TencentLocationListener listener) {
        if (listener != null) {
            mTencentLocationListeners.remove(listener);
        }
    }
  • 开始/关闭模拟轨迹
代码语言:txt
AI代码解释
复制
    /*
     * 模拟轨迹
     * @param context
     * @param fileName 轨迹文件绝对路径
     */
    public void startMockTencentLocation(String fileName, boolean is84) {

       // 首先清除以前的data
        mDatas.clear();
        // 判断是否是84坐标系
        mIsMockTencentLocation = !is84;
        BufferedReader reader = null;
        try {
            File file = new File(fileName);
            InputStream is = new FileInputStream(file);
            reader = new BufferedReader(new InputStreamReader(is));

            String line;
            while ((line = reader.readLine()) != null) {
                mDatas.add(line);
            }
            if (mDatas.size() > 0) {
                mIsReplaying = true;
                synchronized (this) {
                    mPause = false;
                }
                // 开启异步线程
                mMockGpsProviderTask = new Thread(this);
                mMockGpsProviderTask.start();
            }
        } catch (Exception e) {
            Log.e(TAG, "startMockTencentLocation Exception", e);
            e.printStackTrace();
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (Exception e) {
                Log.e(TAG, "startMockTencentLocation Exception", e);
                e.printStackTrace();
            }
        }
    }
代码语言:txt
AI代码解释
复制
    /**
     * 退出应用前也需要调用停止模拟位置,否则手机的正常GPS定位不会恢复
     */
    public void stopMockTencentLocation() {
        try {
            mIsReplaying = false;
            mMockGpsProviderTask.join();
            mMockGpsProviderTask = null;
            lastPointTime = 0;
        } catch (Exception e) {
            Log.e(TAG, "stopMockTencentLocation Exception", e);
            e.printStackTrace();
        }
    }
  • runnable相关
代码语言:txt
AI代码解释
复制
 @Override
    public void run() {
        for (String line : mDatas) {
            if (!mIsReplaying) {
                Log.e(TAG, "stop gps replay");
                break;
            }
            if (TextUtils.isEmpty(line)) {
                continue;
            }

            try {
                Thread.sleep(getSleepTime(line) * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            boolean mockResult;
            mockResult = mockTencentLocation(line);
            if (!mockResult) {
                break;
            }

            try {
                checkToPauseThread();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

使用到的private方法

代码语言:txt
AI代码解释
复制
private void checkToPauseThread() throws InterruptedException {
        synchronized (this) {
            while (mPause) {
                wait();
            }
        }
}

private int getSleepTime(String line) {
    try {
        String[] parts = line.split(",");
        double time = Double.valueOf(parts[6]);
        time = (int) Math.floor(time);
        if(lastPointTime != 0) {
            sleepTime = time  - lastPointTime; // 单位s,取整数
        }
        lastPointTime = time;
    }catch (Exception e) {
    
    }
    return (int)sleepTime;
}

private boolean mockTencentLocation(String line) {
    try {
        String[] parts = line.split(",");

        double latitude = Double.valueOf(parts[1]);
        double longitude = Double.valueOf(parts[0]);
        float accuracy = Float.valueOf(parts[2]);
        float bearing = Float.valueOf(parts[3]);
        float speed = Float.valueOf(parts[4]);
        double altitude = Double.valueOf(parts[7]);
        double time = Double.valueOf(parts[6]);

        String buildingId;
        String floorName;
        if (parts.length >= 10) {
            buildingId = parts[8];
            floorName = parts[9];
        } else {
            buildingId = "";
            floorName = "";
        }

        if (!mIsMockTencentLocation) {
            double[] result = CoordinateConverter.wgs84togcj02(longitude, latitude);
            longitude = result[0];
            latitude = result[1];
        }

        GpsPlaybackEngine.MyTencentLocation location = new GpsPlaybackEngine.MyTencentLocation();
        location.setProvider("gps");
        location.setLongitude(longitude);
        location.setLatitude(latitude);
        location.setAccuracy(accuracy);
        location.setDirection(bearing);
        location.setVelocity(speed);
        location.setAltitude(altitude);
        location.setBuildingId(buildingId);
        location.setFloorName(floorName);
        location.setRssi(4);
        location.setTime(System.currentTimeMillis());
//			location.setTime((long) time * 1000);

        for (TencentLocationListener listener : mTencentLocationListeners) {
            if (listener != null) {
                String curTime;
                if (location != null && location.getTime() != 0) {
                    long millisecond = location.getTime();
                    Date date = new Date(millisecond);
                    SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd hh:mm:ss");
                    curTime = format.format(date);
                } else {
                    curTime = "null";
                }
                Log.e(TAG, "time : " + curTime
                        + ", longitude : " + longitude
                        + " , latitude : " + latitude);

                listener.onLocationChanged(location, 0, "");
                listener.onStatusUpdate(LocationManager.GPS_PROVIDER, mMockGpsStatus, "");
            }
        }
    } catch(Exception e) {
        Log.e(TAG, "Mock Location Exception", e);
        // 如果未开位置模拟,这里可能出异常
        e.printStackTrace();
        return false;
    }
    return true;
}

CoordinateConverter.wg84togcj02

代码语言:txt
AI代码解释
复制
	/**
	 * WGS84转GCJ02(火星坐标系)
	 * 
	 * @param lng WGS84坐标系的经度
	 * @param lat WGS84坐标系的纬度
	 * @return 火星坐标数组
	 */
	public static double[] wgs84togcj02(double lng, double lat) {
		if (out_of_china(lng, lat)) {
			return new double[] { lng, lat };
		}
		double dlat = transformlat(lng - 105.0, lat - 35.0);
		double dlng = transformlng(lng - 105.0, lat - 35.0);
		double radlat = lat / 180.0 * pi;
		double magic = Math.sin(radlat);
		magic = 1 - ee * magic * magic;
		double sqrtmagic = Math.sqrt(magic);
		dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi);
		dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * pi);
		double mglat = lat + dlat;
		double mglng = lng + dlng;
		return new double[] { mglng, mglat };
	}

内部类MyTencentLocation implements 定位sdk的接口

代码语言:txt
AI代码解释
复制
class MyTencentLocation implements TencentLocation {
        /**
         * 纬度
         */
        private double latitude = 0;
        /**
         * 经度
         */
        private double longitude = 0;
        /**
         * 精度
         */
        private float accuracy = 0;
        /**
         * gps方向
         */
        private float direction = -1;
        /**
         * 速度
         */
        private float velocity = 0;
        /**
         * 时间
         */
        private long time = 0;
        /**
         * 海拔高度
         */
        private double altitude = 0;
        /**
         * 定位来源
         */
        private String provider = "";
        /**
         * GPS信号等级
         */
        private int rssi = 0;

        /**
         * 手机的机头方向
         */
        private float phoneDirection = -1;

        private String buildingId = "";

        private String floorName = "";

        private  String fusionProvider = "";

        @Override
        public String getProvider() {
            return provider;
        }

        @Override
        public String getSourceProvider() {
            return null;
        }

        @Override
        public String getFusionProvider() {
            return fusionProvider;
        }

        @Override
        public String getCityPhoneCode() {
            return null;
        }

        @Override
        public double getLatitude() {
            return latitude;
        }

        @Override
        public double getLongitude() {
            return longitude;
        }

        @Override
        public double getAltitude() {
            return latitude;
        }

        @Override
        public float getAccuracy() {
            return accuracy;
        }

        @Override
        public String getName() {
            return null;
        }

        @Override
        public String getAddress() {
            return null;
        }

        @Override
        public String getNation() {
            return null;
        }

        @Override
        public String getProvince() {
            return null;
        }

        @Override
        public String getCity() {
            return null;
        }

        @Override
        public String getDistrict() {
            return null;
        }

        @Override
        public String getTown() {
            return null;
        }

        @Override
        public String getVillage() {
            return null;
        }

        @Override
        public String getStreet() {
            return null;
        }

        @Override
        public String getStreetNo() {
            return null;
        }

        @Override
        public Integer getAreaStat() {
            return null;
        }

        @Override
        public List<TencentPoi> getPoiList() {
            return null;
        }

        @Override
        public float getBearing() {
            return direction;
        }

        @Override
        public float getSpeed() {
            return velocity;
        }

        @Override
        public long getTime() {
            return time;
        }

        @Override
        public long getElapsedRealtime() {
            return time;
        }

        @Override
        public int getGPSRssi() {
            return rssi;
        }

        @Override
        public String getIndoorBuildingId() {
            return buildingId;
        }

        @Override
        public String getIndoorBuildingFloor() {
            return floorName;
        }

        @Override
        public int getIndoorLocationType() {
            return 0;
        }

        @Override
        public double getDirection() {
            return phoneDirection;
        }

        @Override
        public String getCityCode() {
            return null;
        }

        @Override
        public TencentMotion getMotion() {
            return null;
        }

        @Override
        public int getGpsQuality() {
            return 0;
        }

        @Override
        public float getDeltaAngle() {
            return 0;
        }

        @Override
        public float getDeltaSpeed() {
            return 0;
        }

        @Override
        public int getCoordinateType() {
            return 0;
        }

        @Override
        public int getFakeReason() {
            return 0;
        }

        @Override
        public int isMockGps() {
            return 0;
        }

        @Override
        public Bundle getExtra() {
            return null;
        }

        @Override
        public int getInOutStatus() {
            return 0;
        }

        public void setLatitude(double latitude) {
            this.latitude = latitude;
        }

        public void setLongitude(double longitude) {
            this.longitude = longitude;
        }

        public void setAccuracy(float accuracy) {
            this.accuracy = accuracy;
        }

        public void setDirection(float direction) {
            this.direction = direction;
        }

        public void setVelocity(float velocity) {
            this.velocity = velocity;
        }

        public void setTime(long time) {
            this.time = time;
        }

        public void setAltitude(double altitude) {
            this.altitude = altitude;
        }

        public void setProvider(String provider) {
            this.provider = provider;
        }

        public void setFusionProvider(String fusionProvider) { this.fusionProvider = fusionProvider; }

        public void setRssi(int rssi) {
            this.rssi = rssi;
        }

        public void setPhoneDirection(float phoneDirection) {
            this.phoneDirection = phoneDirection;
        }

        public void setBuildingId(String buildingId) {
            this.buildingId = buildingId;
        }

        public void setFloorName(String floorName) {
            this.floorName = floorName;
        }
    }

效果展示

最终根据已经录制好的轨迹(具体录制方法可以参见上期腾讯位置服务轨迹录制-安卓篇),从中国技术交易大厦到北京西站的gps轨迹进行回放,并通过导航sdk进行展示如下

tutieshi_640x1386_65s.gif
tutieshi_640x1386_65s.gif

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
腾讯位置服务GPS轨迹录制-安卓篇
在地图的使用中,尤其在导航场景下,进行GPS轨迹录制是十分必要并且有用的,本文会对于安卓系统下的轨迹录制部分做一个分享。
腾讯位置服务
2021/05/14
1.1K0
微信模拟位置想在哪就在哪(GPS欺骗)
微信模拟位置是通过位置欺骗,让微信误以为我们就在当前的位置进行周边好友的搜索与添加。
全栈程序员站长
2022/08/12
2.8K0
微信模拟位置想在哪就在哪(GPS欺骗)
使用Xposed进行微信小程序API的hook
  上一篇文章讲了安卓的虚拟定位相关的内容,最后编写了一个frida脚本来对Framework层的API进行hook实现虚拟定位。但是有几点局限性:
大A
2023/02/14
7.3K0
腾讯位置服务实现路径规划功能demo
这个腾讯位置服务产品初体验小demo能够实现的基本功能有:实现输入(定位)当前位置及终点位置,在地图上规划出两点之间路线,并显示路线所需的距离及路费,确认行程后通过动画模拟车辆在路线上行驶。
腾讯位置服务
2021/08/04
1.2K0
腾讯位置服务实现路径规划功能demo
GPS用户定位
现在的手机大多数都提供了GPS模块、通过GPS模块可以接收GPS信号,并可精确地指定目前所在的位置,如果将GPS定位功能应用到地图上,还可以实现导航、搜索公交、搜索驾车路线等实用且有趣功能。本章中我们先学习GPS的基本知识,然后通过具体的案例讲解Android环境中GPS开发的基本原理及步骤。学习过本章知识之后我们能够利用GPS进行简单的定位功能的开发。学习本章的重点是掌握LocationManager、LocationProvider与LocationListener等API的功能和用法,并可以通过它们来监听、获取GPS定位信息。
张哥编程
2024/12/17
3310
GPS用户定位
读取图片文件中的位置等meta信息
读取图片文件中的meta信息: <dependency> <groupId>com.drewnoakes</groupId> <artifactId>metadata-extractor</artifactId> <version>2.11.0</version> </dependency> Metadata metadata; try { metadata = ImageMetadataReader.readMetadata
yawn
2019/03/12
1.3K0
安卓—项目中插入百度地图sdk
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/116586.html原文链接:https://javaforall.cn
全栈程序员站长
2022/07/07
9300
腾讯位置服务打车乘客端小车平滑移动-安卓篇
当使用打车软件打车时,我们会好奇司机在送乘客的时候,乘客的手机并没有在导航,那到底是如何做到的呢?今天我们来揭开它神秘的面纱
腾讯位置服务
2021/06/18
9480
Google Map
上一章介绍了如何使用Android的GPS来获取设备的定位信息,但这种方式得到的定位信息只不过是一些数字的经度、纬度值,如果这些经度、纬度值不能以更加形象、直观的方式显示出来,对于大部分普通用户而言,这些数据几乎没有任何价值。要想让这些经纬度值“派上”用场,就需要用到本章中介绍到的Google Map服务。在本章中我们首先对Google Map进行简单的介绍,然后介绍Android中进行Google Map开发需要的准备工作,最后通过一系列的案例讲解了在Android中进行Google Map开发的方法及技巧。
张哥编程
2024/12/17
5380
Google Map
安卓MVP框架的简介与搭建
MVP是Model-View-Presenter的简称,即模型-视图-表现层的缩写。MVP是由MVP模式进化而来的,MVP改进了MVC中的控制器过于臃肿的问题。 与MVC一样,MVP将应用程序的数据处理、数据显示和逻辑控制分开,用一种业务逻辑、数据显示和界面相分离的方法组织代码。
緣來
2020/01/02
1.7K0
安卓MVP框架的简介与搭建
【探花交友】day07—搜附近
探花功能是将推荐的好友随机的通过卡片的形式展现出来,用户可以选择左滑、右滑操作,左滑:“不喜欢”,右滑:“喜欢”。
陶然同学
2023/04/12
1.2K0
【探花交友】day07—搜附近
Arcgis API for Android之GPS定位
先说说写这篇文章的原因吧,在群内讨论的过程中,有人提到了定位的问题,刚好,自己以前在做相关工作的时候做过相关的东西,所以就总结一下,给大家共享出来,由于本人水平有限,bug是在所难免,还望有更高的高人批评指正。废话不多说,直接进入主题。
牛老师讲GIS
2018/10/23
9700
Android开发笔记(一百零三)地图与定位SDK
国内常用的地图SDK就是百度和高德了,二者的用法大同小异,可按照官网上的开发指南一步步来。下面是我在集成地图SDK时遇到的问题说明: 1、点击基本地图功能选项,不能打开地图,弹出“key验证出错!请在AndroidManifest.xml文件中检查key设置的”的红色字提示。查看日志提示“galaxy lib host missing meta-data,make sure you know the right way to integrate galaxy” 该问题是因为key值对应的签名与app打包用的签名不一致。app在开发时与发布时有两个不同的签名,开发时用的是ADT默认签名,查看默认签名的SHA1值可依次选择“Window”->“Preferences”->“Android”->“Build  SHA1 fingerprint”。app发布时的签名是密钥文件的签名,查看发布签名的SHA1值可依次选择“File”->“Export”->“Export Android Application”->“Next”后选择密钥文件并输入密码与app输出路径->在“Certificate fingerprints”下查看SHA1值。 2、百度地图SDK3.6及以上版本找不到overlayutil包。 这是因为新版SDK的jar包不再包含这部分源码,得到官方demo的src目录下获取源码加入到开发者自己的工程中,源码路径为:BaiduMap_AndroidMapSDK_v3.7.1_Sample\BaiduMapsApiDemo\src\com\baidu\mapapi 3、在一个工程中同时包含了百度地图和高德地图的sdk,编译时报错“Found duplicate file for APK: assets/lineDashTexture.png”。 这是因为百度和高德的sdk,其jar包存在同名文件“assets/lineDashTexture.png”,所以无法通过编译。即百度sdk与高德sdk是互斥的,不能同时存在于同个工程中,必须分开来使用。
aqi00
2019/01/18
1.7K0
android开发_Location位置定位
新建项目: 1 New Android Project-> 2 Project name:Location 3 Build Target:Android 2.2 4 Application name:
Hongten
2018/09/13
1.1K0
android开发_Location位置定位
安卓端GB28181设备接入模块如何实现实时位置订阅(MobilePosition)
实时位置(MobilePosition)订阅和上报,对GB28281设备接入终端尤其重要,如移动单兵设备、执法记录仪、智能安全帽、车载终端等,Android国标接入设备通过获取到实时经纬度信息,按照一定的间隔上报到国标服务平台,国标服务平台通过如电子地图,实时动态显示前端设备的定位信息,从而实现前端接入设备的可视可控管理。比如4G/5G执法仪,智能安全帽,智能警用头盔,单兵等。
音视频牛哥
2023/10/26
6060
安卓端GB28181设备接入模块如何实现实时位置订阅(MobilePosition)
Arcgis For Android之GPS定位实现
翻开以前做的东西,看了看,很多从逻辑上比较乱,对之做了修改,完成后实现的效果为: MapActivity源代码如下: package com.lzugis.map; import java.io.File; import java.util.Iterator; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.location.Gps
牛老师讲GIS
2018/10/23
1.9K0
[android] 手机卫士手机实现短信指令获取位置
转换标准坐标为火星坐标,数据库文件放到assets目录下,把ModifyOffset.java放在service包下面
唯一Chat
2019/09/10
1.9K0
[android] 手机卫士手机实现短信指令获取位置
Java如何实现定位
最近了不起这边有个项目需求,我们需要知道设备所在的位置,进而进行未来5天的天气预估,做这个就是为了看天气有没有太阳。
灬沙师弟
2023/12/11
5920
Java如何实现定位
腾讯位置服务开发应用-使用教程,案例分享,知识总结
作为一名在职岗位为【前端开发工程师】的程序员,我开发的应用程序经常需要获取用户位置信息,需要再某些场合下使用展示地图以及地图商的某些地点,需要获取行政区划列表(省市区)以及地址详情信息,需要在地图上规划一条(动态)路线,轨迹回放,小车移动,需要创建信息窗口,用于地点的摘要性信息的展示。
达达前端
2020/12/28
6.6K0
腾讯位置服务开发应用-使用教程,案例分享,知识总结
Android GB28181接入端实时位置订阅和上报之-如何获取当前经纬度
我们在做Android平台GB28181的时候,其中实时位置(MobilePosition)订阅和上报这块,涉及到实时经纬度的获取,特别是执法记录、车载系统的那个等场景,几乎就是标配。
音视频牛哥
2022/09/21
7990
推荐阅读
相关推荐
腾讯位置服务GPS轨迹录制-安卓篇
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档