效果图:

这个操作是,先开启手机app的定位权限,左上角开始记录,目的地到达后,再次点击左上角,结束;点击右上角,是记录的轨迹以及你所走的总距离以及时间等;记录的数据是保存在数据库中的;

导入的各类包如下图1、2所示:

图片资源:

以上两张图片把基本的目录结构也贴出来了,不要缺漏了 !

manifest.xml【添加一些必要的权限】

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"package="com.application.locationpath"><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" /><uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /><uses-permissionandroid:name="android.permission.WRITE_SETTINGS"tools:ignore="ProtectedPermissions" /><uses-permissionandroid:name="android.permission.CHANGE_CONFIGURATION"tools:ignore="ProtectedPermissions" /><uses-permission android:name="android.permission.WAKE_LOCK" /><applicationandroid:requestLegacyExternalStorage="true"android:allowBackup="true"android:dataExtractionRules="@xml/data_extraction_rules"android:fullBackupContent="@xml/backup_rules"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.LocationPath"tools:targetApi="31"><activityandroid:name=".MainActivity"android:exported="true"android:screenOrientation="portrait"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activityandroid:name=".RecordActivity"android:screenOrientation="portrait"></activity><activityandroid:name=".RecordShowActivity"android:screenOrientation="portrait" /><meta-dataandroid:name="com.amap.api.v2.apikey"android:value="你的key" /><service android:name="com.amap.api.location.APSService" /></application></manifest>

不知道key怎么获取的,看我上篇文章!

build.gradle(:app) 添加依赖

dependencies {implementation fileTree(include: ['*.jar'], dir: 'libs')implementation 'androidx.appcompat:appcompat:1.3.0'implementation 'com.google.android.material:material:1.4.0'implementation 'androidx.constraintlayout:constraintlayout:2.0.4'testImplementation 'junit:junit:4.13.2'androidTestImplementation 'androidx.test.ext:junit:1.1.3'androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

各类图片我放在百度网盘里,大家需要的自行去取哈

链接:https://pan.baidu.com/s/1BmKquARhydJAdyviNjDJ_A 
提取码:207k

layout布局我在这里也不详细叙述了;我放到百度网盘里,你们有需要的自行去取哦!

链接:https://pan.baidu.com/s/1bTM79fXbEzTQ5wH2ORF0nQ 
提取码:s8pk

java代码:

目录

效果图:

导入的各类包如下图1、2所示:

manifest.xml【添加一些必要的权限】

build.gradle(:app) 添加依赖

java代码:

DbAdapter.java

Util 工具类不可少:

EmulatorService.java

PathRecord.java

RecordAdapter.java

RecordActivity.java

RecordShowActivity.java

MainActivity.java

TraceRePlay.java

首先要将数据库建好:

DbAdapter.java

package com.application.locationpath;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;import android.Manifest;
import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/*** 数据库相关操作,用于存取轨迹记录*/
public class DbAdapter {public static final String KEY_ID = "id";public static final String KEY_DISTANCE = "distance";public static final String KEY_DURATION = "duration";public static final String KEY_SPEED = "averagespeed";public static final String KEY_LINE = "pathline";public static final String KEY_START = "startpoint";public static final String KEY_END = "endpoint";public static final String KEY_DATE = "date";private final static String DATABASE_PATH = android.os.Environment.getExternalStorageDirectory().getAbsolutePath() + "/recordPath";static final String DATABASE_NAME = DATABASE_PATH + "/" + "record.db";private static final int DATABASE_VERSION = 1;private static final String RECORD_TABLE = "record";private static final String RECORD_CREATE = "create table if not exists record("+ KEY_ID+ " integer primary key autoincrement,"+ "startpoint STRING,"+ "endpoint STRING,"+ "pathline STRING,"+ "distance STRING,"+ "duration STRING,"+ "averagespeed STRING,"+ "date STRING" + ");";public static class DatabaseHelper extends SQLiteOpenHelper {public DatabaseHelper(Context context) {super(context, context.getFilesDir() + "/" + "record.db", null, DATABASE_VERSION);}@Overridepublic void onCreate(SQLiteDatabase db) {db.execSQL(RECORD_CREATE);}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}}private Context mCtx;private DatabaseHelper dbHelper;private SQLiteDatabase db;// constructorpublic DbAdapter(Context ctx) {this.mCtx = ctx;dbHelper = new DatabaseHelper(mCtx);}public void open() throws SQLException {db = dbHelper.getWritableDatabase();}public void close() {dbHelper.close();}public Cursor getall() {return db.rawQuery("SELECT * FROM record", null);}// remove an entrypublic boolean delete(long rowId) {return db.delete(RECORD_TABLE, "id=" + rowId, null) > 0;}/*** 数据库存入一条轨迹*/public long createrecord(String distance, String duration,String averagespeed, String pathline, String startpoint,String endpoint, String date) {ContentValues args = new ContentValues();args.put("distance", distance);args.put("duration", duration);args.put("averagespeed", averagespeed);args.put("pathline", pathline);args.put("startpoint", startpoint);args.put("endpoint", endpoint);args.put("date", date);return db.insert(RECORD_TABLE, null, args);}/*** 查询所有轨迹记录*/@SuppressLint("Range")public List<PathRecord> queryRecordAll() {List<PathRecord> allRecord = new ArrayList<PathRecord>();Cursor allRecordCursor = db.query(RECORD_TABLE, getColumns(), null,null, null, null, null);while (allRecordCursor.moveToNext()) {PathRecord record = new PathRecord();record.setId(allRecordCursor.getInt(allRecordCursor.getColumnIndex(DbAdapter.KEY_ID)));record.setDistance(allRecordCursor.getString(allRecordCursor.getColumnIndex(DbAdapter.KEY_DISTANCE)));record.setDuration(allRecordCursor.getString(allRecordCursor.getColumnIndex(DbAdapter.KEY_DURATION)));record.setDate(allRecordCursor.getString(allRecordCursor.getColumnIndex(DbAdapter.KEY_DATE)));String lines = allRecordCursor.getString(allRecordCursor.getColumnIndex(DbAdapter.KEY_LINE));record.setPathline(Util.parseLocations(lines));record.setStartpoint(Util.parseLocation(allRecordCursor.getString(allRecordCursor.getColumnIndex(DbAdapter.KEY_START))));record.setEndpoint(Util.parseLocation(allRecordCursor.getString(allRecordCursor.getColumnIndex(DbAdapter.KEY_END))));allRecord.add(record);}Collections.reverse(allRecord);return allRecord;}/*** 按照id查询*/@SuppressLint("Range")public PathRecord queryRecordById(int mRecordItemId) {String where = KEY_ID + "=?";String[] selectionArgs = new String[]{String.valueOf(mRecordItemId)};Cursor cursor = db.query(RECORD_TABLE, getColumns(), where,selectionArgs, null, null, null);PathRecord record = new PathRecord();if (cursor.moveToNext()) {record.setId(cursor.getInt(cursor.getColumnIndex(DbAdapter.KEY_ID)));record.setDistance(cursor.getString(cursor.getColumnIndex(DbAdapter.KEY_DISTANCE)));record.setDuration(cursor.getString(cursor.getColumnIndex(DbAdapter.KEY_DURATION)));record.setDate(cursor.getString(cursor.getColumnIndex(DbAdapter.KEY_DATE)));String lines = cursor.getString(cursor.getColumnIndex(DbAdapter.KEY_LINE));record.setPathline(Util.parseLocations(lines));record.setStartpoint(Util.parseLocation(cursor.getString(cursor.getColumnIndex(DbAdapter.KEY_START))));record.setEndpoint(Util.parseLocation(cursor.getString(cursor.getColumnIndex(DbAdapter.KEY_END))));}return record;}private String[] getColumns() {return new String[]{KEY_ID, KEY_DISTANCE, KEY_DURATION, KEY_SPEED,KEY_LINE, KEY_START, KEY_END, KEY_DATE};}
}

Util 工具类不可少:

package com.application.locationpath;import java.util.ArrayList;
import java.util.List;import com.amap.api.location.AMapLocation;
import com.amap.api.maps.model.LatLng;
import com.amap.api.trace.TraceLocation;public class Util {/*** 将AMapLocation List 转为TraceLocation list*/public static List<TraceLocation> parseTraceLocationList(List<AMapLocation> list) {List<TraceLocation> traceList = new ArrayList<>();if (list == null) {return traceList;}for (int i = 0; i < list.size(); i++) {TraceLocation location = new TraceLocation();AMapLocation amapLocation = list.get(i);location.setBearing(amapLocation.getBearing());location.setLatitude(amapLocation.getLatitude());location.setLongitude(amapLocation.getLongitude());location.setSpeed(amapLocation.getSpeed());location.setTime(amapLocation.getTime());traceList.add(location);}return traceList;}public static TraceLocation parseTraceLocation(AMapLocation amapLocation) {TraceLocation location = new TraceLocation();location.setBearing(amapLocation.getBearing());location.setLatitude(amapLocation.getLatitude());location.setLongitude(amapLocation.getLongitude());location.setSpeed(amapLocation.getSpeed());location.setTime(amapLocation.getTime());return  location;}/*** 将AMapLocation List 转为LatLng list*/public static List<LatLng> parseLatLngList(List<AMapLocation> list) {List<LatLng> traceList = new ArrayList<>();if (list == null) {return traceList;}for (int i = 0; i < list.size(); i++) {AMapLocation loc = list.get(i);double lat = loc.getLatitude();double lng = loc.getLongitude();LatLng latlng = new LatLng(lat, lng);traceList.add(latlng);}return traceList;}public static AMapLocation parseLocation(String latLonStr) {if (latLonStr == null || latLonStr.equals("") || latLonStr.equals("[]")) {return null;}String[] loc = latLonStr.split(",");AMapLocation location = null;if (loc.length == 6) {location = new AMapLocation(loc[2]);location.setProvider(loc[2]);location.setLatitude(Double.parseDouble(loc[0]));location.setLongitude(Double.parseDouble(loc[1]));location.setTime(Long.parseLong(loc[3]));location.setSpeed(Float.parseFloat(loc[4]));location.setBearing(Float.parseFloat(loc[5]));}else if(loc.length == 2){location = new AMapLocation("gps");location.setLatitude(Double.parseDouble(loc[0]));location.setLongitude(Double.parseDouble(loc[1]));}return location;}public static ArrayList<AMapLocation> parseLocations(String latLonStr) {ArrayList<AMapLocation> locations = new ArrayList<>();String[] latLonStrs = latLonStr.split(";");for (int i = 0; i < latLonStrs.length; i++) {AMapLocation location = Util.parseLocation(latLonStrs[i]);if (location != null) {locations.add(location);}}return locations;}
}

EmulatorService.java

package com.application.locationpath;import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.location.provider.ProviderProperties;
import android.os.Binder;
import android.os.IBinder;
import android.os.SystemClock;
import android.provider.Settings;
import android.text.TextUtils;public class EmulatorService extends Service {public static double latitude;public static double longitude;public boolean isMockOpen() {String strMock = Settings.Secure.ALLOW_MOCK_LOCATION;strMock = Settings.Secure.getString(getApplicationContext().getContentResolver(), strMock);if (!TextUtils.isEmpty(strMock) && !strMock.equals("0")) {return true;}return false;}private Thread thread = new Thread() {public void run() {while (true) {if (latitude == 0 || longitude == 0) {try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}continue;}if(!isMockOpen()){try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}continue;}LocationManager locmanag = (LocationManager) EmulatorService.this.getSystemService(Context.LOCATION_SERVICE);String mock = LocationManager.GPS_PROVIDER;locmanag.addTestProvider(mock, false, true, false, false,false, false, false, ProviderProperties.POWER_USAGE_LOW, ProviderProperties.ACCURACY_FINE);locmanag.setTestProviderEnabled(mock, true);Location loc = new Location(mock);loc.setTime(System.currentTimeMillis());// 下面这两句很关键loc.setLatitude(latitude);loc.setLongitude(longitude);loc.setAccuracy(Criteria.ACCURACY_FINE);// 精确度loc.setSpeed(50);if (android.os.Build.VERSION.SDK_INT >= 17) {loc.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());// 实时运行时间}locmanag.setTestProviderStatus(mock,LocationProvider.AVAILABLE, null,System.currentTimeMillis());locmanag.setTestProviderLocation(mock, loc);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}};@Overridepublic IBinder onBind(Intent intent) {thread.start();// TODO Auto-generated method stubreturn new EmulatorBinder();}public class EmulatorBinder extends Binder {public void setEmulatorLocation(double latitude, double longitude) {setLocation(latitude, longitude);}}private void setLocation(double latitude, double longitude) {this.latitude = latitude;this.longitude = longitude;}
}

PathRecord.java

package com.application.locationpath;import java.util.ArrayList;
import java.util.List;
import com.amap.api.location.AMapLocation;/*** 用于记录一条轨迹,包括起点、终点、轨迹中间点、距离、耗时、平均速度、时间*/
public class PathRecord {private AMapLocation mStartPoint;private AMapLocation mEndPoint;private List<AMapLocation> mPathLinePoints = new ArrayList<AMapLocation>();private String mDistance;private String mDuration;private String mAveragespeed;private String mDate;private int mId = 0;public int getId() {return mId;}public void setId(int id) {this.mId = id;}public AMapLocation getStartpoint() {return mStartPoint;}public void setStartpoint(AMapLocation startpoint) {this.mStartPoint = startpoint;}public AMapLocation getEndpoint() {return mEndPoint;}public void setEndpoint(AMapLocation endpoint) {this.mEndPoint = endpoint;}public List<AMapLocation> getPathline() {return mPathLinePoints;}public void setPathline(List<AMapLocation> pathline) {this.mPathLinePoints = pathline;}public String getDistance() {return mDistance;}public void setDistance(String distance) {this.mDistance = distance;}public String getDuration() {return mDuration;}public void setDuration(String duration) {this.mDuration = duration;}public String getAveragespeed() {return mAveragespeed;}public void setAveragespeed(String averagespeed) {this.mAveragespeed = averagespeed;}public String getDate() {return mDate;}public void setDate(String date) {this.mDate = date;}public void addpoint(AMapLocation point) {mPathLinePoints.add(point);}@Overridepublic String toString() {StringBuilder record = new StringBuilder();record.append("recordSize:" + getPathline().size() + ", ");record.append("distance:" + getDistance() + "m, ");record.append("duration:" + getDuration() + "s");return record.toString();}
}

RecordAdapter.java

package com.application.locationpath;import java.util.List;import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;public class RecordAdapter extends BaseAdapter {private final Context mContext;private final List<PathRecord> mRecordList;public RecordAdapter(Context context, List<PathRecord> list) {this.mContext = context;this.mRecordList = list;}@Overridepublic int getCount() {return mRecordList.size();}@Overridepublic Object getItem(int position) {return mRecordList.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder;if (convertView == null) {holder = new ViewHolder();convertView = View.inflate(mContext, R.layout.record_item, null);holder.date = convertView.findViewById(R.id.date);holder.record = convertView.findViewById(R.id.record);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}PathRecord item = mRecordList.get(position);holder.date.setText(item.getDate());holder.record.setText(item.toString());return convertView;}private static class ViewHolder {TextView date;TextView record;}
}

RecordActivity.java

package com.application.locationpath;import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.Toast;import androidx.appcompat.app.AppCompatActivity;import com.amap.api.location.AMapLocation;
import com.amap.api.maps.MapsInitializer;import java.util.ArrayList;
import java.util.List;/*** 所有轨迹list展示activity**/
public class RecordActivity extends AppCompatActivity implements OnItemClickListener {private RecordAdapter mAdapter;private ListView mAllRecordListView;private DbAdapter mDataBaseHelper;private List<PathRecord> mAllRecord = new ArrayList<PathRecord>();public static final String RECORD_ID = "record_id";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.record_list);MapsInitializer.updatePrivacyShow(this,true,true);MapsInitializer.updatePrivacyAgree(this,true);mAllRecordListView = findViewById(R.id.recordlist);mDataBaseHelper = new DbAdapter(this);mDataBaseHelper.open();searchAllRecordFromDB();//        if (list != null && list.size() > 0) {
//            DbHelper = new DbAdapter(this);
//            DbHelper.open();
//            String duration = getDuration();
//            float distance = getDistance(list);
//            String average = getAverage(distance);
//            String pathlineString = getPathLineString(list);
//            AMapLocation firstLocation = list.get(0);
//            AMapLocation lastLocation = list.get(list.size() - 1);
//            String startpoint = amapLocationToString(firstLocation);
//            String endpoint = amapLocationToString(lastLocation);// 测试数据是否插入成功mDataBaseHelper.createrecord("ass","ass","ass","ass","ass","ass","ass");searchAllRecordFromDB();
//            DbHelper.close();
//        } else {
//            Toast.makeText(MainActivity.this, "没有记录到路径", Toast.LENGTH_SHORT)
//                    .show();
//        }mAdapter = new RecordAdapter(this, mAllRecord);mAllRecordListView.setAdapter(mAdapter);mAllRecordListView.setOnItemClickListener(this);}private void searchAllRecordFromDB() {mAllRecord = mDataBaseHelper.queryRecordAll();}public void onBackClick(View view) {this.finish();}@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position,long id) {PathRecord recorditem = (PathRecord) parent.getAdapter().getItem(position);Intent intent = new Intent(RecordActivity.this,RecordShowActivity.class);intent.putExtra(RECORD_ID, recorditem.getId());startActivity(intent);}
}

RecordShowActivity.java

package com.application.locationpath;import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.RadioButton;
import android.widget.Toast;
import android.widget.ToggleButton;import androidx.appcompat.app.AppCompatActivity;import com.amap.api.location.AMapLocation;
import com.amap.api.maps.AMap;
import com.amap.api.maps.AMap.OnMapLoadedListener;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.MapView;
import com.amap.api.maps.MapsInitializer;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.LatLngBounds;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.Polyline;
import com.amap.api.maps.model.PolylineOptions;
import com.amap.api.trace.LBSTraceClient;
import com.amap.api.trace.TraceListener;
import com.amap.api.trace.TraceLocation;import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** 实现轨迹回放、纠偏后轨迹回放**/
public class RecordShowActivity extends AppCompatActivity implementsOnMapLoadedListener, TraceListener, OnClickListener {private final static int AMAP_LOADED = 2;private RadioButton mOriginRadioButton, mGraspRadioButton;private ToggleButton mDisplaybtn;private MapView mMapView;private AMap mAMap;private Marker mOriginStartMarker, mOriginEndMarker, mOriginRoleMarker;private Marker mGraspStartMarker, mGraspEndMarker, mGraspRoleMarker;private Polyline mOriginPolyline, mGraspPolyline;private int mRecordItemId;private List<LatLng> mOriginLatLngList;private List<LatLng> mGraspLatLngList;private boolean mGraspChecked = false;private boolean mOriginChecked = true;private ExecutorService mThreadPool;private TraceRePlay mRePlay;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.record_display_activity);MapsInitializer.updatePrivacyShow(this,true,true);MapsInitializer.updatePrivacyAgree(this,true);mMapView = findViewById(R.id.map);mMapView.onCreate(savedInstanceState);// 此方法必须重写mGraspRadioButton = findViewById(R.id.record_show_activity_grasp_radio_button);mOriginRadioButton = findViewById(R.id.record_show_activity_origin_radio_button);mOriginRadioButton.setOnClickListener(this);mGraspRadioButton.setOnClickListener(this);mDisplaybtn = findViewById(R.id.displaybtn);mDisplaybtn.setOnClickListener(this);Intent recordIntent = getIntent();int threadPoolSize = Runtime.getRuntime().availableProcessors() * 2 + 3;mThreadPool = Executors.newFixedThreadPool(threadPoolSize);if (recordIntent != null) {mRecordItemId = recordIntent.getIntExtra(RecordActivity.RECORD_ID,-1);}initMap();}private void initMap() {if (mAMap == null) {mAMap = mMapView.getMap();mAMap.setOnMapLoadedListener(this);}}private void startMove() {if(mRePlay !=null){mRePlay.stopTrace();}if (mOriginChecked) {mRePlay = rePlayTrace(mOriginLatLngList, mOriginRoleMarker);} else if (mGraspChecked) {mRePlay = rePlayTrace(mGraspLatLngList, mGraspRoleMarker);}}/*** 轨迹回放方法*/private TraceRePlay rePlayTrace(List<LatLng> list, final Marker updateMarker) {TraceRePlay replay = new TraceRePlay(list, 100,new TraceRePlay.TraceRePlayListener() {@Overridepublic void onTraceUpdating(LatLng latLng) {if (updateMarker != null) {updateMarker.setPosition(latLng); // 更新小人实现轨迹回放}}@Overridepublic void onTraceUpdateFinish() {mDisplaybtn.setChecked(false);mDisplaybtn.setClickable(true);}});mThreadPool.execute(replay);return replay;}/*** 将纠偏后轨迹小人设置到起点*/private void resetGraspRole() {if (mGraspLatLngList == null) {return;}LatLng startLatLng = mGraspLatLngList.get(0);if (mGraspRoleMarker != null) {mGraspRoleMarker.setPosition(startLatLng);}}/*** 将原始轨迹小人设置到起点*/private void resetOriginRole() {if (mOriginLatLngList == null) {return;}LatLng startLatLng = mOriginLatLngList.get(0);if (mOriginRoleMarker != null) {mOriginRoleMarker.setPosition(startLatLng);}}@SuppressLint("HandlerLeak")private Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);if (msg.what == AMAP_LOADED) {try {setupRecord();} catch (Exception e) {e.printStackTrace();}}}};public void onBackClick(View view) {this.finish();if (mThreadPool != null) {mThreadPool.shutdownNow();}}public void onDestroy() {super.onDestroy();if (mThreadPool != null) {mThreadPool.shutdownNow();}}private LatLngBounds getBounds() {LatLngBounds.Builder b = LatLngBounds.builder();if (mOriginLatLngList == null) {return b.build();}for (int i = 0; i < mOriginLatLngList.size(); i++) {b.include(mOriginLatLngList.get(i));}return b.build();}/*** 轨迹数据初始化*/private void setupRecord() throws Exception {// 轨迹纠偏初始化LBSTraceClient mTraceClient = new LBSTraceClient(getApplicationContext());DbAdapter dbhelper = new DbAdapter(this.getApplicationContext());dbhelper.open();PathRecord mRecord = dbhelper.queryRecordById(mRecordItemId);dbhelper.close();if (mRecord != null) {List<AMapLocation> recordList = mRecord.getPathline();AMapLocation startLoc = mRecord.getStartpoint();AMapLocation endLoc = mRecord.getEndpoint();if (recordList == null || startLoc == null || endLoc == null) {return;}LatLng startLatLng = new LatLng(startLoc.getLatitude(),startLoc.getLongitude());LatLng endLatLng = new LatLng(endLoc.getLatitude(),endLoc.getLongitude());mOriginLatLngList = Util.parseLatLngList(recordList);addOriginTrace(startLatLng, endLatLng, mOriginLatLngList);List<TraceLocation> mGraspTraceLocationList = Util.parseTraceLocationList(recordList);// 调用轨迹纠偏,将mGraspTraceLocationList进行轨迹纠偏处理mTraceClient.queryProcessedTrace(1, mGraspTraceLocationList,LBSTraceClient.TYPE_AMAP, this);}}/*** 地图上添加原始轨迹线路及起终点、轨迹动画小人*/private void addOriginTrace(LatLng startPoint, LatLng endPoint,List<LatLng> originList) {mOriginPolyline = mAMap.addPolyline(new PolylineOptions().color(Color.BLUE).addAll(originList));mOriginStartMarker = mAMap.addMarker(new MarkerOptions().position(startPoint).icon(BitmapDescriptorFactory.fromResource(R.drawable.start)));mOriginEndMarker = mAMap.addMarker(new MarkerOptions().position(endPoint).icon(BitmapDescriptorFactory.fromResource(R.drawable.end)));try {mAMap.moveCamera(CameraUpdateFactory.newLatLngBounds(getBounds(),50));} catch (Exception e) {e.printStackTrace();}mOriginRoleMarker = mAMap.addMarker(new MarkerOptions().position(startPoint).icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.walk))));}/*** 设置是否显示原始轨迹*/private void setOriginEnable(boolean enable) {mDisplaybtn.setClickable(true);if (mOriginPolyline != null && mOriginStartMarker != null&& mOriginEndMarker != null && mOriginRoleMarker != null) {if (enable) {mOriginPolyline.setVisible(true);mOriginStartMarker.setVisible(true);mOriginEndMarker.setVisible(true);mOriginRoleMarker.setVisible(true);} else {mOriginPolyline.setVisible(false);mOriginStartMarker.setVisible(false);mOriginEndMarker.setVisible(false);mOriginRoleMarker.setVisible(false);}}}/*** 地图上添加纠偏后轨迹线路及起终点、轨迹动画小人*/private void addGraspTrace(List<LatLng> graspList, boolean mGraspChecked) {if (graspList != null && graspList.size() >= 2) {LatLng startPoint = graspList.get(0);LatLng endPoint = graspList.get(graspList.size() - 1);mGraspPolyline = mAMap.addPolyline(new PolylineOptions().setCustomTexture(BitmapDescriptorFactory.fromResource(R.drawable.grasp_trace_line)).width(40).addAll(graspList));mGraspStartMarker = mAMap.addMarker(new MarkerOptions().position(startPoint).icon(BitmapDescriptorFactory.fromResource(R.drawable.start)));mGraspEndMarker = mAMap.addMarker(new MarkerOptions().position(endPoint).icon(BitmapDescriptorFactory.fromResource(R.drawable.end)));mGraspRoleMarker = mAMap.addMarker(new MarkerOptions().position(startPoint).icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.walk))));if (!mGraspChecked) {mGraspPolyline.setVisible(false);mGraspStartMarker.setVisible(false);mGraspEndMarker.setVisible(false);mGraspRoleMarker.setVisible(false);}}}/*** 设置是否显示纠偏后轨迹*/private void setGraspEnable(boolean enable) {mDisplaybtn.setClickable(true);if (mGraspPolyline != null && mGraspStartMarker != null&& mGraspEndMarker != null && mGraspRoleMarker != null) {if (enable) {mGraspPolyline.setVisible(true);mGraspStartMarker.setVisible(true);mGraspEndMarker.setVisible(true);mGraspRoleMarker.setVisible(true);} else {mGraspPolyline.setVisible(false);mGraspStartMarker.setVisible(false);mGraspEndMarker.setVisible(false);mGraspRoleMarker.setVisible(false);}}}@Overridepublic void onMapLoaded() {Message msg = handler.obtainMessage();msg.what = AMAP_LOADED;handler.sendMessage(msg);}/*** 轨迹纠偏完成数据回调*/@Overridepublic void onFinished(int arg0, List<LatLng> list, int arg2, int arg3) {addGraspTrace(list, mGraspChecked);mGraspLatLngList = list;}@Overridepublic void onRequestFailed(int arg0, String arg1) {Toast.makeText(this.getApplicationContext(), "轨迹纠偏失败:" + arg1,Toast.LENGTH_SHORT).show();}@Overridepublic void onTraceProcessing(int arg0, int arg1, List<LatLng> arg2) {}@SuppressLint("NonConstantResourceId")@Overridepublic void onClick(View v) {int id = v.getId();switch (id) {case R.id.displaybtn:if (mDisplaybtn.isChecked()) {startMove();mDisplaybtn.setClickable(false);}break;case R.id.record_show_activity_grasp_radio_button:mGraspChecked = true;mOriginChecked = false;mGraspRadioButton.setChecked(true);mOriginRadioButton.setChecked(false);setGraspEnable(true);setOriginEnable(false);mDisplaybtn.setChecked(false);resetGraspRole();break;case R.id.record_show_activity_origin_radio_button:mOriginChecked = true;mGraspChecked = false;mGraspRadioButton.setChecked(false);mOriginRadioButton.setChecked(true);setGraspEnable(false);setOriginEnable(true);mDisplaybtn.setChecked(false);resetOriginRole();break;}}
}

MainActivity.java

package com.application.locationpath;import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;import androidx.appcompat.app.AppCompatActivity;import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationClientOption.AMapLocationMode;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps.AMap;
import com.amap.api.maps.AMapUtils;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.LocationSource;
import com.amap.api.maps.MapView;
import com.amap.api.maps.MapsInitializer;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.Polyline;
import com.amap.api.maps.model.PolylineOptions;
import com.amap.api.trace.LBSTraceClient;
import com.amap.api.trace.TraceListener;
import com.amap.api.trace.TraceLocation;
import com.amap.api.trace.TraceOverlay;import java.text.DecimalFormat;
import java.text.SimpleDateFormat;import java.util.ArrayList;
import java.util.Date;
import java.util.List;public class MainActivity extends AppCompatActivity implements LocationSource,AMapLocationListener, TraceListener {private MapView mMapView;private AMap mAMap;private OnLocationChangedListener mListener;private AMapLocationClient mLocationClient;private AMapLocationClientOption mLocationOption;private PolylineOptions mPolyoptions;private Polyline mpolyline;private PathRecord record;private long mStartTime;private long mEndTime;private ToggleButton btn;   //状态按钮开关 turn on   or   turn offprivate DbAdapter DbHelper;private List<TraceLocation> mTracelocationlist = new ArrayList<TraceLocation>();private List<TraceOverlay> mOverlayList = new ArrayList<TraceOverlay>();private List<AMapLocation> recordList = new ArrayList<AMapLocation>();private int traceSize = 30;private int mDistance = 0;private TraceOverlay mTraceOverlay;     // 轨迹纠偏private TextView mResultShow;private Marker mlocMarker;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.basic_map_activity);MapsInitializer.updatePrivacyShow(this,true,true);MapsInitializer.updatePrivacyAgree(this,true);mMapView = findViewById(R.id.map);mMapView.onCreate(savedInstanceState);// 此方法必须重写init();   //初始化AMap对象initpolyline();}private void init() {if (mAMap == null) {mAMap = mMapView.getMap();setUpMap();}btn = findViewById(R.id.locationbtn);btn.setOnClickListener(new OnClickListener() {@SuppressLint("SetTextI18n")@Overridepublic void onClick(View v) {if (btn.isChecked()) {mAMap.clear(true);if (record != null) {record = null;}record = new PathRecord();mStartTime = System.currentTimeMillis();record.setDate(getcueDate(mStartTime));mResultShow.setText("总距离");} else {mEndTime = System.currentTimeMillis();mOverlayList.add(mTraceOverlay);DecimalFormat decimalFormat = new DecimalFormat("0.0");mResultShow.setText(decimalFormat.format(getTotalDistance() / 1000d) + "KM");LBSTraceClient mTraceClient = null;try {mTraceClient = new LBSTraceClient(getApplicationContext());} catch (Exception e) {e.printStackTrace();}assert mTraceClient != null;mTraceClient.queryProcessedTrace(2, Util.parseTraceLocationList(record.getPathline()) , LBSTraceClient.TYPE_AMAP, MainActivity.this);saveRecord(record.getPathline(), record.getDate());}}});mResultShow = findViewById(R.id.show_all_dis);mTraceOverlay = new TraceOverlay(mAMap);}protected void saveRecord(List<AMapLocation> list, String time) {if (list != null && list.size() > 0) {DbHelper = new DbAdapter(this);DbHelper.open();String duration = getDuration();float distance = getDistance(list);String average = getAverage(distance);String pathlineString = getPathLineString(list);AMapLocation firstLocation = list.get(0);AMapLocation lastLocation = list.get(list.size() - 1);String startpoint = amapLocationToString(firstLocation);String endpoint = amapLocationToString(lastLocation);DbHelper.createrecord(String.valueOf(distance), duration, average,pathlineString, startpoint, endpoint, time);DbHelper.close();} else {Toast.makeText(MainActivity.this, "没有记录到路径", Toast.LENGTH_SHORT).show();}}private String getDuration() {return String.valueOf((mEndTime - mStartTime) / 1000f);}private String getAverage(float distance) {return String.valueOf(distance / (float) (mEndTime - mStartTime));}private float getDistance(List<AMapLocation> list) {float distance = 0;if (list == null || list.size() == 0) {return distance;}for (int i = 0; i < list.size() - 1; i++) {AMapLocation firstpoint = list.get(i);AMapLocation secondpoint = list.get(i + 1);LatLng firstLatLng = new LatLng(firstpoint.getLatitude(),firstpoint.getLongitude());LatLng secondLatLng = new LatLng(secondpoint.getLatitude(),secondpoint.getLongitude());double betweenDis;betweenDis = AMapUtils.calculateLineDistance(firstLatLng,secondLatLng);distance = (float) (distance + betweenDis);}return distance;}private String getPathLineString(List<AMapLocation> list) {if (list == null || list.size() == 0) {return "";}StringBuffer pathline = new StringBuffer();for (int i = 0; i < list.size(); i++) {AMapLocation location = list.get(i);String locString = amapLocationToString(location);pathline.append(locString).append(";");}String pathLineString = pathline.toString();pathLineString = pathLineString.substring(0, pathLineString.length() - 1);return pathLineString;}private String amapLocationToString(AMapLocation location) {StringBuffer locString = new StringBuffer();locString.append(location.getLatitude()).append(",");locString.append(location.getLongitude()).append(",");locString.append(location.getProvider()).append(",");locString.append(location.getTime()).append(",");locString.append(location.getSpeed()).append(",");locString.append(location.getBearing());return locString.toString();}private void initpolyline() {mPolyoptions = new PolylineOptions();mPolyoptions.width(10f);mPolyoptions.color(Color.GRAY);PolylineOptions tracePolytion = new PolylineOptions();tracePolytion.width(40);tracePolytion.setCustomTexture(BitmapDescriptorFactory.fromResource(R.drawable.grasp_trace_line));}/*** 设置一些amap的属性*/private void setUpMap() {mAMap.setLocationSource(this);// 设置定位监听mAMap.getUiSettings().setMyLocationButtonEnabled(true);// 设置默认定位按钮是否显示mAMap.setMyLocationEnabled(true);// 设置为true表示显示定位层并可触发定位,false表示隐藏定位层并不可触发定位,默认是false// 设置定位的类型为定位模式 ,可以由定位、跟随或地图根据面向方向旋转几种mAMap.setMyLocationType(AMap.LOCATION_TYPE_LOCATE);}/*** 方法必须重写*/@Overrideprotected void onResume() {super.onResume();mMapView.onResume();}@Overrideprotected void onPause() {super.onPause();mMapView.onPause();}@Overrideprotected void onSaveInstanceState(Bundle outState) {super.onSaveInstanceState(outState);mMapView.onSaveInstanceState(outState);}@Overrideprotected void onDestroy() {super.onDestroy();mMapView.onDestroy();}@Overridepublic void activate(OnLocationChangedListener listener) {mListener = listener;try {startlocation();} catch (Exception e) {e.printStackTrace();}}@Overridepublic void deactivate() {mListener = null;if (mLocationClient != null) {mLocationClient.stopLocation();mLocationClient.onDestroy();}mLocationClient = null;}/*** 定位结果回调* @param amapLocation 位置信息类*/@Overridepublic void onLocationChanged(AMapLocation amapLocation) {if (mListener != null && amapLocation != null) {if (amapLocation.getErrorCode() == 0) {mListener.onLocationChanged(amapLocation);// 显示系统小蓝点LatLng mylocation = new LatLng(amapLocation.getLatitude(),amapLocation.getLongitude());mAMap.moveCamera(CameraUpdateFactory.changeLatLng(mylocation));if (btn.isChecked()) {record.addpoint(amapLocation);mPolyoptions.add(mylocation);mTracelocationlist.add(Util.parseTraceLocation(amapLocation));redrawline();if (mTracelocationlist.size() > traceSize - 1) {try {trace();} catch (Exception e) {e.printStackTrace();}}}} else {String errText = "定位失败," + amapLocation.getErrorCode() + ": "+ amapLocation.getErrorInfo();Log.e("AmapErr", errText);}}}/*** 开始定位。*/private void startlocation() throws Exception {if (mLocationClient == null) {mLocationClient = new AMapLocationClient(this);mLocationOption = new AMapLocationClientOption();// 设置定位监听mLocationClient.setLocationListener(this);// 设置为高精度定位模式mLocationOption.setLocationMode(AMapLocationMode.Hight_Accuracy);mLocationOption.setInterval(2000);// 设置定位参数mLocationClient.setLocationOption(mLocationOption);mLocationClient.startLocation();}}/*** 实时轨迹画线*/private void redrawline() {if (mPolyoptions.getPoints().size() > 1) {if (mpolyline != null) {mpolyline.setPoints(mPolyoptions.getPoints());} else {mpolyline = mAMap.addPolyline(mPolyoptions);}}}@SuppressLint("SimpleDateFormat")private String getcueDate(long time) {SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd  HH:mm:ss ");Date curDate = new Date(time);String date = formatter.format(curDate);final String date1 = date;return date1;}public void record(View view) {Intent intent = new Intent(MainActivity.this, RecordActivity.class);startActivity(intent);}private void trace() throws Exception {List<TraceLocation> locationList = new ArrayList<>(mTracelocationlist);LBSTraceClient mTraceClient = new LBSTraceClient(getApplicationContext());mTraceClient.queryProcessedTrace(1, locationList, LBSTraceClient.TYPE_AMAP, this);TraceLocation lastlocation = mTracelocationlist.get(mTracelocationlist.size()-1);mTracelocationlist.clear();mTracelocationlist.add(lastlocation);}@Overridepublic void onRequestFailed(int i, String s) {}/*** 轨迹纠偏失败回调。*/@Overridepublic void onTraceProcessing(int i, int i1, List<LatLng> list) {}/*** 轨迹纠偏成功回调。*/@Overridepublic void onFinished(int lineID, List<LatLng> linepoints, int distance, int waitingtime) {if (lineID == 1) {if (linepoints != null && linepoints.size()>0) {mTraceOverlay.add(linepoints);mDistance += distance;mTraceOverlay.setDistance(mTraceOverlay.getDistance()+distance);if (mlocMarker == null) {mlocMarker = mAMap.addMarker(new MarkerOptions().position(linepoints.get(linepoints.size() - 1)).icon(BitmapDescriptorFactory.fromResource(R.drawable.point)).title("距离:" + mDistance+"米"));mlocMarker.showInfoWindow();} else {mlocMarker.setTitle("距离:" + mDistance+"米");Toast.makeText(MainActivity.this, "距离"+mDistance, Toast.LENGTH_SHORT).show();mlocMarker.setPosition(linepoints.get(linepoints.size() - 1));mlocMarker.showInfoWindow();}}} else if (lineID == 2) if (linepoints != null && linepoints.size() > 0) {mAMap.addPolyline(new PolylineOptions().color(Color.RED).width(40).addAll(linepoints));}}/*** 最后获取总距离*/private int getTotalDistance() {int distance = 0;for (TraceOverlay to : mOverlayList) {distance = distance + to.getDistance();}return distance;}
}

TraceRePlay.java

package com.application.locationpath;import java.lang.ref.WeakReference;
import java.util.List;import android.os.Handler;
import android.os.Looper;
import android.os.Message;import com.amap.api.maps.model.LatLng;/*** 轨迹回放工具类* */
public class TraceRePlay implements Runnable {private TraceRePlayHandler mTraceHandler;private static final int TRACE_MOVE = 1;private static final int TRACE_FINISH = 2;private List<LatLng> mTraceList;private int mIntervalMillisecond;private TraceRePlayListener mTraceUpdateListener;private boolean mStop = false;/*** 构造轨迹回放需要,List、时间间隔、回调listener* * @param list*            轨迹list* @param intervalMillisecond*            回调时间间隔* @param listener*            回调listener*/public TraceRePlay(List<LatLng> list, int intervalMillisecond,TraceRePlayListener listener) {mTraceList = list;mIntervalMillisecond = intervalMillisecond;mTraceUpdateListener = listener;mTraceHandler = new TraceRePlayHandler(this);}public void stopTrace() {mStop = true;}/*** 接收run发送的消息,达到按照设定时间间隔轮巡轨迹list目的* */static class TraceRePlayHandler extends Handler {WeakReference<TraceRePlay> mTraceRePlay;public TraceRePlayHandler(TraceRePlay traceRePlay) {super(Looper.getMainLooper());mTraceRePlay = new WeakReference<TraceRePlay>(traceRePlay);}@Overridepublic void handleMessage(Message message) {super.handleMessage(message);TraceRePlay trace = mTraceRePlay.get();switch (message.what) {case TRACE_MOVE:LatLng latLng = (LatLng) message.obj;if (trace.mTraceUpdateListener != null) {trace.mTraceUpdateListener.onTraceUpdating(latLng);}break;case TRACE_FINISH:if (trace.mTraceUpdateListener != null) {trace.mTraceUpdateListener.onTraceUpdateFinish();}break;default:break;}}}public interface TraceRePlayListener {// 轨迹回放过程回调void onTraceUpdating(LatLng latLng);//轨迹回放结束回调void onTraceUpdateFinish();}/*** 将 mTraceList 按照给定的时间间隔和次序发消息给TraceRePlayHandler以达到轨迹回放效果*/@Overridepublic void run() {if (mTraceList != null) {for (int i = 0; i < mTraceList.size(); i++) {if (mStop) {break;}LatLng latLng = mTraceList.get(i);Message message = mTraceHandler.obtainMessage();message.what = TRACE_MOVE;message.obj = latLng;mTraceHandler.sendMessage(message);try {Thread.sleep(mIntervalMillisecond);} catch (InterruptedException e) {e.printStackTrace();}}if (!mStop) {Message finishMessage = mTraceHandler.obtainMessage();finishMessage.what = TRACE_FINISH;mTraceHandler.sendMessage(finishMessage);}}}
}

android studio的版本不同,盲目搬用的话可能会出现许多问题,大家一定要看看我的版本哦!

我的android版本:11.0.12

我的gradle版本:7.3.3

我的jdk版本:1.8

内容挺多的哈,大家要有耐心哦!!!需要安装包的话评论区私我即可!

高德地图定位、足迹跟踪,轨迹记录复现【2023年】相关推荐

  1. 安卓开发 高德地图定位的封装 十分钟上手

    前言 地图作为开发中三方sdk中较常遇到的一项,集成起来并不麻烦但是不小心踩坑可能会浪费较多时间,如果项目中多处使用还容易造成代码大量冗余,今天我们来将高德地图定位功能集成一个功能化模块,只需两分钟应 ...

  2. android中高德地图定位功能并且获取定位的城市

    一.概述 今天再一次用到了地图定位功能和地图显示功能,以前一直用的是高德地图定位,这次还是用高德,记录一下以便以后再做时方便一些.因为业务需要的功能不是很全,可以参考https://www.2cto. ...

  3. 关于高德地图定位跑到非洲的情况。

    在这记录高德地图定位的相关问题. 1.高德地图定位之后跑到非洲那边过去了. 原因是因为 sha1没有设置对,或者只设置对了一个,线上或者测试环境下. 测试环境下的sha1如果设置对了,就可以避免打包后 ...

  4. flutter 获取定位_从头开发一个Flutter插件(二)高德地图定位插件

    在上一篇文章从头开发一个Flutter插件(一)开发流程里具体介绍了flutter插件的具体开发流程,从创建项目到发布.接下来将会为Flutter天气项目开发一个基于高德定位sdk的flutter定位 ...

  5. Android MVVM框架搭建(八)高德地图定位、天气查询、BottomSheetDialog

    Android MVVM框架搭建(八)高德地图定位.天气查询.BottomSheetDialog 前言 正文 一.集成SDK 二.基础配置 ① 权限配置 ② 配置Key 三.显示地图 ① MapFra ...

  6. 使用高德地图API实现历史轨迹查询

        欢迎大家关注我的公众号,有问题可以及时和我交流. 使用高德地图API完成历史轨迹查询 创作背景 相关技术 设计思路 实现难点 编码实现 实现效果 创作背景 因为对历史轨迹查询比较好奇,所以使用 ...

  7. RN导入高德地图定位的用法实例

    转载自:[译]React Native开源高德地图定位组件(react-native-amap-location) -江清清的技术专栏 1.NPM install 1 npm install relo ...

  8. android 地图定位失败,Android 高德地图定位遇到的异常

    最近项目中集成了高德地图定位功能,使用都是正常按照高德开发文档来的,目前出现的问题是退出整个应用程序时(应用的主界面显示地图同时开启了实时定位),报错误如下: 12-26 10:21:56.739 2 ...

  9. android 定位工具类,高德地图定位工具类

    引言 定位功能初始化设置时耗时较多,如果放在Activity中操作,难免会有Activity切换较慢的问题.通过该工具类,可以实现一次初始化,多处随时调用.具有占用资源少,使用方便,便于复用,速度快, ...

  10. 高德地图定位的简单实现

    1.要实现高德地图的定位,首先要下载高德地图的SDK以及高德地图定位的SDK 下载地址:http://lbs.amap.com/api/android-sdk/download/ http://lbs ...

最新文章

  1. SAP零售行业解决方案初阶 4 – 维护品类
  2. 轻量级DAO层实践初体验
  3. 《左手MongoDB右手Redis》第3章笔记-robo3t上进行增删改查
  4. 【渝粤教育】国家开放大学2018年春季 0703-22T经济学基础 参考试题
  5. godot python_我的godot开发环境调教记录分享
  6. PowerCmd(命令行增强工具) 2.2 免费版
  7. matlab bs2rv.m,matlab遗传算法工具箱中的例子不能用?
  8. linux curl 特殊字符,遇到问题--curl--- url参数中有+、空格、=、%、、#等特殊符号的导致传参不全 | 易学教程...
  9. js模板引擎template.js的使用
  10. 手动安装K8s第五节:master节点kubectl命令部署
  11. redis中hget命令
  12. 最小径集的算法_最小割集Stoer-Wagner算法 | 学步园
  13. Leetcode520Detect Capital检测大写字母
  14. 数学传奇1——群星闪耀时
  15. 手把手教你做最实用的数据分析模板——帕累托法则
  16. 用js写卡牌游戏(五)
  17. mysql-Util
  18. 数据库-订单发票表(单表)
  19. 图像处理学习笔记之——绪论
  20. js防抖、节流(立即执行/非立即执行 + 立即取消等待)

热门文章

  1. vue 响应拦截器不起作用
  2. 逻辑回归二分类算法python_多分类逻辑回归 (Multinomial Logistic Regression)
  3. 网购学会7招 从此菜鸟变高手
  4. Linux系统(ubuntu)部署Asp.Net Core网站
  5. MEM/MBA英语基础(09)倒装句
  6. iOS 抽奖轮盘效果实现思路
  7. java开发的代码规范
  8. JAVA 开发统一规范(规约)
  9. Ardunio开发——水泵操作过程
  10. Kubernetes学习(八)Helm应用包管理器