2024年最新腾讯地图GPS轨迹回放-安卓篇,2024年最新中国移动开发岗面试

总结

最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的Android开发中高级必知必会核心笔记,共计2968页PDF、58w字,囊括Android开发648个知识点,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

2021年虽然路途坎坷,都在说Android要没落,但是,不要慌,做自己的计划,学自己的习,竞争无处不在,每个行业都是如此。相信自己,没有做不到的,只有想不到的。

虽然面试失败了,但我也不会放弃入职字节跳动的决心的!建议大家面试之前都要有充分的准备,顺顺利利的拿到自己心仪的offer。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

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()

可以使用导航SDK的算路方法并且获取算路成功和失败的回调

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

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

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

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());
}
}

结束导航

@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机制

public class GpsPlaybackEngine implements Runnable{

// 代码在下方
}

而使用到的fields

// Tencent轨迹Mock, TencentLocationListener需要利用腾讯定位SDK获取
private ArrayList mTencentLocationListeners = new ArrayList<>();

// 获取的location数据
private List mDatas = new ArrayList();

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相关

// 添加listener
public void addTencentLocationListener(TencentLocationListener listener) {
if (listener != null) {
mTencentLocationListeners.add(listener);
}
}

// 移除listener
public void removeTencentLocationListener(TencentLocationListener listener) {
if (listener != null) {
mTencentLocationListeners.remove(listener);
}
}

  • 开始/关闭模拟轨迹

/*

  • 模拟轨迹
  • @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();
}
}
}

/**

  • 退出应用前也需要调用停止模拟位置,否则手机的正常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相关

@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方法

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

/**

  • 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的接口

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 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) {

题外话

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在IT学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多程序员朋友无法获得正确的资料得到学习提升,故此将并将重要的Android进阶资料包括自定义view、性能优化、MVC与MVP与MVVM三大框架的区别、NDK技术、阿里面试题精编汇总、常见源码分析等学习资料。

【Android思维脑图(技能树)】

知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。

希望我能够用我的力量帮助更多迷茫、困惑的朋友们,帮助大家在IT道路上学习和发展~

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

外话

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在IT学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多程序员朋友无法获得正确的资料得到学习提升,故此将并将重要的Android进阶资料包括自定义view、性能优化、MVC与MVP与MVVM三大框架的区别、NDK技术、阿里面试题精编汇总、常见源码分析等学习资料。

【Android思维脑图(技能树)】

知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。

[外链图片转存中…(img-b9ghiQDw-1715220230861)]

希望我能够用我的力量帮助更多迷茫、困惑的朋友们,帮助大家在IT道路上学习和发展~

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值