最后
对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。
同时我经过多年的收藏目前也算收集到了一套完整的学习资料以及高清详细的Android架构进阶学习导图及笔记分享给大家,希望对想成为架构师的朋友有一定的参考和帮助。
下面是部分资料截图,诚意满满:特别适合有开发经验的Android程序员们学习。
不论遇到什么困难,都不应该成为我们放弃的理由!
如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言,一定会认真查询,修正不足,谢谢。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
}
@Override
protected void onDestroy() {
// 退出时销毁定位
mLocClient.stop();
// 关闭定位图层
mBaiduMap.setMyLocationEnabled(false);
mMapView.onDestroy();
mMapView = null;
super.onDestroy();
}
在 AndroidManifest.xml中声明Service,这一步很关键,不写则无法定位:
<service
android:name=“com.baidu.location.f”
android:enabled=“true”
android:process=“:remote” >
当然,Key也是不可或缺,而且必须正确的:
<meta-data
android:name=“com.baidu.lbsapi.API_KEY”
android:value=“************************” />
最后,在AndroidManifest.xml文件中要加入需要的权限:
到此就大功告成了。
记录轨迹思路
-
用Service获取经纬度,onCreate中开始采集经纬度点,保存到ArrayList
-
每隔5秒取样一次,若经纬度未发生变化,丢弃该次取样
-
在onDestroy中,将ArrayList转成JSON格式,然后存储到SDCard中
显示轨迹思路
-
读取目录下所有轨迹文件,并生成ListView
-
在OnItemClick中将文件名称通过intent.putExtra传递给显示轨迹的Activity
-
根据文件名将对应的JSON内容转成ArrayList
-
然后将以上ArrayList的点集依次连线,并绘制到百度地图上
-
设置起始点Marker,Zoom级别,中心点为起始点
-
轨迹点小于2个无法绘制轨迹,给出提示
初步Demo效果图,获取的经纬度有偏移,明天看看哪里的问题:
先贴一个保存经纬度点的Service的核心代码:
public class RouteRecordService extends Service {
private LocationClient mLocationClient;
private final String ROUTE_PATH = “/sdcard/Route/”;
private String startTime = “”;
private String stopTime = “”;
private List list = new ArrayList();
private RouteAdapter adapter = new RouteAdapter();
private int startId = 1; // 轨迹点初始ID
private int defaultDelay = 5000; // 轨迹点取样间隔时间:ms
private final static double ERROR_CODE = 55.555;
private double routeLng;
private double routeLat;
private boolean isEncrypt = false; // true:读取百度加密经纬度 false:读取设备提供经纬度
private boolean isDebug = true;
// 设备定位经纬度
private enum DeviceLocType {
LATITUDE, LONGITUDE
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
super.onCreate();
InitLocation(LocationMode.Hight_Accuracy, “gcj02”, 1000, false);
// 初始化路径
File filestoreMusic = new File(ROUTE_PATH);
if (!filestoreMusic.exists()) {
filestoreMusic.mkdir();
}
startTime = getTimeStr();
if (isDebug) {
Toast.makeText(getApplicationContext(), “Start Record Route”,
Toast.LENGTH_SHORT).show();
}
// 开启轨迹记录线程
new Thread(new RouteRecordThread()).start();
}
public class RouteRecordThread implements Runnable {
@Override
public void run() {
while (true) {
try {
Thread.sleep(defaultDelay);
Message message = new Message();
message.what = 1;
recordHandler.sendMessage(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
final Handler recordHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
startRecordRoute();
}
super.handleMessage(msg);
}
};
private void startRecordRoute() {
// 获取设备经纬度
if (!isEncrypt) {
routeLat = getDeviceLocation(DeviceLocType.LATITUDE);
routeLng = getDeviceLocation(DeviceLocType.LONGITUDE);
if (isDebug)
Toast.makeText(getApplicationContext(),
“Device Loc:” + routeLat + “,” + routeLng,
Toast.LENGTH_SHORT).show();
}
RoutePoint routePoint = new RoutePoint();
if (routeLng != 5.55 && routeLat != 5.55) {
if (list.size() > 0
&& list.get(list.size() - 1).getLat() == routeLat
&& (list.get(list.size() - 1).getLng() == routeLng)) {
if (isDebug) {
// Toast.makeText(getApplicationContext(),
// “Route not change”,
// Toast.LENGTH_SHORT).show();
}
} else {
routePoint.setId(startId++);
routePoint.setLng(routeLng);
routePoint.setLat(routeLat);
list.add(routePoint);
}
}
}
/**
-
获取设备提供的经纬度,Network或GPS
-
@param type
-
请求经度还是纬度
-
@return
*/
private double getDeviceLocation(DeviceLocType type) {
double deviceLat = ERROR_CODE;
double deviceLng = ERROR_CODE;
LocationManager locationManager = (LocationManager) getSystemService(getApplicationContext().LOCATION_SERVICE);
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
Location location = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
deviceLat = location.getLatitude();
deviceLng = location.getLongitude();
} else {
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, 1000, 0,
new deviceLocationListener());
Location location1 = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location1 != null) {
deviceLat = location1.getLatitude(); // 经度
deviceLng = location1.getLongitude(); // 纬度
}
}
} else {
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, 1000, 0,
new deviceLocationListener());
Location location = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
deviceLat = location.getLatitude(); // 经度
deviceLng = location.getLongitude(); // 纬度
}
}
if (type == DeviceLocType.LATITUDE)
return deviceLat;
else if (type == DeviceLocType.LONGITUDE)
return deviceLng;
else
return ERROR_CODE;
}
/**
-
设备位置监听器
*/
class deviceLocationListener implements LocationListener {
// Provider的状态在可用、暂时不可用和无服务三个状态直接切换时触发此函数
public void onStatusChanged(String provider, int status, Bundle extras) {
}
// Provider被enable时触发此函数,比如GPS被打开
@Override
public void onProviderEnabled(String provider) {
}
// Provider被disable时触发此函数,比如GPS被关闭
@Override
public void onProviderDisabled(String provider) {
}
// 当坐标改变时触发此函数,如果Provider传进相同的坐标,它就不会被触发
@Override
public void onLocationChanged(Location location) {
// routeLat = location.getLatitude(); // 经度
// routeLng = location.getLongitude(); // 纬度
}
};
private String getTimeStr() {
long nowTime = System.currentTimeMillis();
Date date = new Date(nowTime);
String strs = “” + ERROR_CODE;
try {
SimpleDateFormat sdf = new SimpleDateFormat(“yyyyMMdd_HHmmss”);
strs = sdf.format(date);
} catch (Exception e) {
e.printStackTrace();
}
return strs;
}
/**
-
初始化轨迹文件路径和名称
-
@return String
*/
private String getFilePath() {
stopTime = getTimeStr();
String format = “.json”;
if (isDebug)
format = “.txt”;
return ROUTE_PATH + startTime + “-” + stopTime + format;
}
class MyLocationListener implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
// 读取百度加密经纬度
if (isEncrypt) {
routeLng = location.getLongitude();
routeLat = location.getLatitude();
}
}
}
}
优化轨迹平滑度:
同一数据,优化前后效果对比:
优化算法:
public List optimizePoints(List inPoint) {
int size = inPoint.size();
List outPoint;
int i;
if (size < 5) {
return inPoint;
} else {
// Latitude
inPoint.get(0)
.setLat((3.0 * inPoint.get(0).getLat() + 2.0
- inPoint.get(1).getLat() + inPoint.get(2).getLat() - inPoint
.get(4).getLat()) / 5.0);
inPoint.get(1)
.setLat((4.0 * inPoint.get(0).getLat() + 3.0
-
inPoint.get(1).getLat() + 2
-
inPoint.get(2).getLat() + inPoint.get(3).getLat()) / 10.0);
inPoint.get(size - 2).setLat(
(4.0 * inPoint.get(size - 1).getLat() + 3.0
-
inPoint.get(size - 2).getLat() + 2
-
inPoint.get(size - 3).getLat() + inPoint.get(
size - 4).getLat()) / 10.0);
inPoint.get(size - 1).setLat(
(3.0 * inPoint.get(size - 1).getLat() + 2.0
- inPoint.get(size - 2).getLat()
- inPoint.get(size - 3).getLat() - inPoint.get(
size - 5).getLat()) / 5.0);
// Longitude
inPoint.get(0)
.setLng((3.0 * inPoint.get(0).getLng() + 2.0
- inPoint.get(1).getLng() + inPoint.get(2).getLng() - inPoint
.get(4).getLng()) / 5.0);
inPoint.get(1)
.setLng((4.0 * inPoint.get(0).getLng() + 3.0
-
inPoint.get(1).getLng() + 2
-
inPoint.get(2).getLng() + inPoint.get(3).getLng()) / 10.0);
inPoint.get(size - 2).setLng(
(4.0 * inPoint.get(size - 1).getLng() + 3.0
-
inPoint.get(size - 2).getLng() + 2
-
inPoint.get(size - 3).getLng() + inPoint.get(
size - 4).getLng()) / 10.0);
inPoint.get(size - 1).setLng(
(3.0 * inPoint.get(size - 1).getLng() + 2.0
- inPoint.get(size - 2).getLng()
- inPoint.get(size - 3).getLng() - inPoint.get(
size - 5).getLng()) / 5.0);
}
return inPoint;
}
截取轨迹图片并分享
@@ -1,14 +1,24 @@
package com.zms.baidulbs;
+import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.util.EncodingUtils;
import android.app.Activity;
+import android.content.Intent;
import android.content.SharedPreferences;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.net.Uri;
import android.os.Bundle;
+import android.view.View;
+import android.view.Window;
import android.widget.Button;
import android.widget.Toast;
@@ -24,6 +34,7 @@
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.map.PolylineOptions;
import com.baidu.mapapi.map.BaiduMap.OnMarkerClickListener;
+import com.baidu.mapapi.map.BaiduMap.SnapshotReadyCallback;
import com.baidu.mapapi.map.InfoWindow.OnInfoWindowClickListener;
import com.baidu.mapapi.model.LatLng;
import com.zms.baidulbs.R;
@@ -34,11 +45,13 @@
private InfoWindow mInfoWindow;
private Marker mMarkerStart;
private Marker mMarkerEnd;
- private Button btnShare, btnBack;
public double mRouteLatitude = 0.0;
public double mRouteLongitude = 0.0;
private final String ROUTE_PATH = “/sdcard/Route/”;
- private String filePath = “”;
private RouteAdapter routeAdapter = new RouteAdapter();
// 初始化全局 bitmap 信息,不用时及时 recycle
@@ -51,13 +64,22 @@
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.route_show);
- String filePath = “”;
-
// Hide Status Bar
-
View decorView = getWindow().getDecorView();
-
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
-
btnShare = (Button) findViewById(R.id.btnShare);
-
btnBack = (Button) findViewById(R.id.btnBack);
-
btnShare.setOnClickListener(new MyOnClickListener());
-
btnBack.setOnClickListener(new MyOnClickListener());
Bundle extras = getIntent().getExtras();
if (extras != null) {
filePath = extras.getString(“filePath”);
- setTitle(filePath.substring(0, filePath.length() - 4));
- // setTitle(filePath.substring(0, filePath.length() - 4));
} else {
Toast.makeText(getApplicationContext(), “轨迹文件不存在”,
Toast.LENGTH_SHORT).show();
@@ -71,6 +93,51 @@ protected void onCreate(Bundle savedInstanceState) {
}
-
class MyOnClickListener implements View.OnClickListener {
-
@Override
-
public void onClick(View v) {
-
switch (v.getId()) {
-
case R.id.btnShare:
最后
由于文章篇幅原因,我只把面试题列了出来,详细的答案,我整理成了一份PDF文档,这份文档还包括了还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 ,帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
er());
Bundle extras = getIntent().getExtras();
if (extras != null) {
filePath = extras.getString(“filePath”);
- setTitle(filePath.substring(0, filePath.length() - 4));
- // setTitle(filePath.substring(0, filePath.length() - 4));
} else {
Toast.makeText(getApplicationContext(), “轨迹文件不存在”,
Toast.LENGTH_SHORT).show();
@@ -71,6 +93,51 @@ protected void onCreate(Bundle savedInstanceState) {
}
-
class MyOnClickListener implements View.OnClickListener {
-
@Override
-
public void onClick(View v) {
-
switch (v.getId()) {
-
case R.id.btnShare:
最后
由于文章篇幅原因,我只把面试题列了出来,详细的答案,我整理成了一份PDF文档,这份文档还包括了还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 ,帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!