获取秘钥
添加权限
//获取设备网络状态,禁用后无法获取网络状态
//网络权限,当禁用后,无法进行检索等相关业务
//读取设备硬件信息,统计数据
//读取系统信息,包含系统版本等信息,用作统计
//获取设备的网络状态,鉴权所需网络代理
//允许sd卡写权限,需写入地图数据,禁用后无法显示地图
//这个权限用于进行网络定位
//这个权限用于访问GPS定位
//获取统计数据
//使用步行AR导航,配置Camera权限
//程序在手机屏幕关闭后后台进程仍然运行
声明定位的service组件
package com.example.track;
import java.util.ArrayList;
public class Track {
private int id;
private String track_name;
private String create_date;
private String start_loc;
private String end_loc;
private ArrayList trackDetails;
public Track(int id, String track_name, String create_date, String start_loc, String end_loc) {
super();
this.id = id;
this.track_name = track_name;
this.create_date = create_date;
this.start_loc = start_loc;
this.end_loc = end_loc;
}
public Track(String track_name, String create_date, String start_loc, String end_loc) {
super();
this.track_name = track_name;
this.create_date = create_date;
this.start_loc = start_loc;
this.end_loc = end_loc;
}
public Track(){super();}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTrack_name() {
return track_name;
}
public void setTrack_name(String track_name) {
this.track_name = track_name;
}
public String getCreate_date() {
return create_date;
}
public void setCreate_date(String create_date) {
this.create_date = create_date;
}
public String getStart_loc() {
return start_loc;
}
public void setStart_loc(String start_loc) {
this.start_loc = start_loc;
}
public String getEnd_loc() {
return end_loc;
}
public void setEnd_loc(String end_loc) {
this.end_loc = end_loc;
}
public ArrayList getTrackDetails() {
return trackDetails;
}
public void setTrackDetails(ArrayList trackDetails) {
this.trackDetails = trackDetails;
}
}
package com.example.track;
public class TrackDetail {
private int id;
private double lat;
private double lag;
private Track track;
public TrackDetail(int id, double lat, double lag) {
super();
this.id = id;
this.lat = lat;
this.lag = lag;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public double getLat() {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
public double getLag() {
return lag;
}
public void setLag(double lag) {
this.lag = lag;
}
public Track getTrack() {
return track;
}
public void setTrack(Track track) {
this.track = track;
}
}
package com.example.track;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DatabaseHelper extends SQLiteOpenHelper {
private static String DB_NAME="track.db";
//表名
public static String TABLE_TRACK="track";
public static String TABLE_TRACK_DETAIL="track_detail";
//字段
public static String ID="_id";
//跟踪表
public static String TRACK_NAME="track_name";
public static String CREATE_DATE="create_date";
public static String START_LOC="start_loc";
public static String END_LOC="end_loc";
//明细表
public static String TID="tid";//线路的id
public static String LAT="lat";//纬度
public static String LNG="lng";//经度
private static String CREATE_TABLE_TRACK="create table track(_id integer primary key autoincrement,track_name text,create_date text,start_loc text,end_loc text)";
private static String CREATE_TABLE_TRACK_DETAIL="create table track_detail(_id integer primary key autoincrement,tid integer not null,lat real,lng real)";
private static int VERSION=1;
public DatabaseHelper(Context context) {
super(context, DB_NAME, null, VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_TABLE_TRACK);
db.execSQL(CREATE_TABLE_TRACK_DETAIL);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (newVersion>oldVersion){
db.execSQL("drop table if exists track");
db.execSQL("drop table if exists track_detail");
db.execSQL(CREATE_TABLE_TRACK);
db.execSQL(CREATE_TABLE_TRACK_DETAIL);
}
}
}
package com.example.track;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import java.util.ArrayList;
public class DatabaseAdapter {
private DatabaseHelper dbHelper;
public DatabaseAdapter(Context context){
dbHelper=new DatabaseHelper(context);
}
//添加线路跟踪
public int addTrack(Track track){
SQLiteDatabase db=dbHelper.getWritableDatabase();
ContentValues values=new ContentValues();
values.put(DatabaseHelper.TRACK_NAME,track.getTrack_name());
values.put(DatabaseHelper.CREATE_DATE,track.getCreate_date());
values.put(DatabaseHelper.START_LOC,track.getStart_loc());
values.put(DatabaseHelper.END_LOC,track.getEnd_loc());
long id=db.insertOrThrow(DatabaseHelper.TABLE_TRACK,null,values);
db.close();
return (int) id;
}
//更新终点地址
public void updateEndLoc(String endLoc,int id){
String sql="update track set end_loc=? where _id=?";
SQLiteDatabase db=dbHelper.getWritableDatabase();
db.execSQL(sql,new Object[]{endLoc,id});
db.close();
}
//添加线路跟踪明细
public void addTrackDetail(int tid,double lat,double lng){
SQLiteDatabase db=dbHelper.getWritableDatabase();
String sql="insert into track_detail(tid,lat,lng) values(?,?,?)";
db.execSQL(sql,new Object[]{tid,lat,lng});
db.close();
}
//根据ID查询线路跟踪
public ArrayList getTrackDetails(int id){
String sql="select _id,lat,lng from track_detail where tid=? order by _id desc";
ArrayList list=new ArrayList();
SQLiteDatabase db=dbHelper.getReadableDatabase();
Cursor c=db.rawQuery(sql,new String[]{String.valueOf(id)});
if (c!=null){
TrackDetail detail=null;
while (c.moveToNext()){
detail=new TrackDetail(c.getInt(0),c.getDouble(1),c.getDouble(2));
list.add(detail);
}
c.close();
}
db.close
return list;
}
//查询所有线路
public ArrayList
package com.example.track;
import android.content.DialogInterface;
import android.os.Handler;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;
import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.MyLocationConfiguration;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.map.PolylineOptions;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.search.core.SearchResult;
import com.baidu.mapapi.search.geocode.GeoCodeResult;
import com.baidu.mapapi.search.geocode.GeoCoder;
import com.baidu.mapapi.search.geocode.OnGetGeoCoderResultListener;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeOption;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeResult;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
public class MainActivity extends AppCompatActivity {
private static final int PLAYBACK_OVER=1;
private MapView mMapView;
private BaiduMap baiduMap;
private LocationClient mLocationClient=null;
private MyLocationListener myLocationListener;
private double currentLat,currentLng;//当前经纬度
private String currentAddr;//当前所有的地址
private DatabaseAdapter dbAdapter;
private GeoCoder geoCoder;
private int currentTrackLineID;//当前跟踪的线路ID
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//初始化SDK
SDKInitializer.initialize(getApplicationContext());
setContentView(R.layout.activity_main);
//获取地图控件引用
mMapView = (MapView) findViewById(R.id.bmapView);
initBaiduMap();//初始化地图,显示我的当前位置
dbAdapter=new DatabaseAdapter(this);
}
private void initBaiduMap() {
baiduMap=mMapView.getMap();
baiduMap.setMyLocationEnabled(true);//打开定位
mLocationClient=new LocationClient(getApplicationContext());//声明LocationClient类
myLocationListener=new MyLocationListener();
mLocationClient.registerLocationListener(myLocationListener);
initLocation();
mLocationClient.start();//开启定位
mLocationClient.requestLocation();//发起定位请求
//用于转化地理编码的监听器
geoCoder=GeoCoder.newInstance();
geoCoder.setOnGetGeoCodeResultListener(new OnGetGeoCoderResultListener() {
@Override
public void onGetGeoCodeResult(GeoCodeResult geoCodeResult) {
}
@Override
public void onGetReverseGeoCodeResult(ReverseGeoCodeResult reverseGeoCodeResult) {
if (reverseGeoCodeResult==null||reverseGeoCodeResult.error!= SearchResult.ERRORNO.NO_ERROR){
//没有检索到结果
}else {
//获取地理编码结果
currentAddr=reverseGeoCodeResult.getAddress();
Log.i("tag",currentAddr);
//更新线路结束位置
dbAdapter.updateEndLoc(currentAddr,currentTrackLineID);
}
}
});
}
/*设置定位参数包括:定位模式(高精度定位模式,低功耗定位模式和仅用设备定位模式),返回坐标类型,是否打开GPS,是否返回地址信息、位置语义化信息、POI信息等等。
LocationClientOption类,该类用来设置定位SDK的定位方式,e.g.:*/
private void initLocation() {
LocationClientOption option = new LocationClientOption();
option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy
);//可选,默认高精度,设置定位模式,高精度,低功耗,仅设备
option.setCoorType("bd09ll");//可选,默认gcj02,设置返回的定位结果坐标系
int span = 5000;
option.setScanSpan(span);//可选,默认0,即仅定位一次,设置发起定位请求的间隔需要大于等于5000ms才是有效的
option.setIsNeedAddress(true);//可选,设置是否需要地址信息,默认不需要
option.setOpenGps(true);//可选,默认false,设置是否使用gps
option.setLocationNotify(true);//可选,默认false,设置是否当gps有效时按照1S1次频率输出GPS结果
option.setIsNeedLocationDescribe(true);//可选,默认false,设置是否需要位置语义化结果,可以在BDLocation.getLocationDescribe里得到,结果类似于“在北京天安门附近”
option.setIsNeedLocationPoiList(true);//可选,默认false,设置是否需要POI结果,可以在BDLocation.getPoiList里得到
option.setIgnoreKillProcess(false);//可选,默认true,定位SDK内部是一个SERVICE,并放到了独立进程,设置是否在stop的时候杀死这个进程,默认不杀死
option.SetIgnoreCacheException(false);//可选,默认false,设置是否收集CRASH信息,默认收集
option.setEnableSimulateGps(false);//可选,默认false,设置是否需要过滤gps仿真结果,默认需要
mLocationClient.setLocOption(option);
}
boolean flag=true;
//位置监听器
class MyLocationListener implements BDLocationListener{
@Override
public void onReceiveLocation(BDLocation bdLocation) {//接收位置信息的回调方法
if (bdLocation!=null && flag){
flag=false;
currentLat=bdLocation.getLatitude();//当前纬度
currentLng=bdLocation.getLongitude();//当前精度
currentAddr=bdLocation.getAddrStr();//当前位置的地址
//构造我的当前位置信息
MyLocationData.Builder builder=new MyLocationData.Builder();
builder.latitude(bdLocation.getLatitude());//设置纬度
builder.longitude(bdLocation.getLongitude());//设置经度
builder.accuracy(bdLocation.getRadius());//设置精度
builder.direction(bdLocation.getDirection());//设置方向
builder.speed(bdLocation.getSpeed());//设置速度
MyLocationData locationData=builder.build();
//把我的位置信息设置到地图上
baiduMap.setMyLocationData(locationData);
//配置我的位置 当前经纬度
LatLng latLng=new LatLng(currentLat,currentLng);
//(跟随态,允不允许显示方向,默认图标)
baiduMap.setMyLocationConfiguration(new MyLocationConfiguration(
MyLocationConfiguration.LocationMode.FOLLOWING,
true,null));
//设置我的位置为地图中心点(缩放级别3-20)
baiduMap.animateMapStatus(MapStatusUpdateFactory.newLatLngZoom(latLng,16));
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main,menu);
return true;
}
//功能菜单项
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.mylocation:
mylocation();//我的位置
break;
case R.id.start_track:
startTrack();//开始跟踪
break;
case R.id.end_track:
endTrack();//结束跟踪
break;
case R.id.track_back:
trackBack();//跟踪回放
break;
default:
break;
}
return true;
}
//我的位置
private void mylocation() {
Toast.makeText(this, "正在定位中...", Toast.LENGTH_SHORT).show();
flag=true;
baiduMap.clear();//清除地图上自定义的图层
baiduMap.setMyLocationEnabled(true);
mLocationClient.requestLocation();//发起定位请求
}
//开始追踪功能
private void startTrack() {
AlertDialog.Builder builder=new AlertDialog.Builder(this);
builder.setTitle("线路跟踪");
builder.setCancelable(true);
final View view=getLayoutInflater().inflate(R.layout.add_track_line_dialog,null);
builder.setView(view);
builder.setPositiveButton("添加", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
EditText et_track_name=view.findViewById(R.id.editText1_track_name);
String trackName=et_track_name.getText().toString();
Log.i("tag",trackName);
createTrack(trackName);//创建线路跟踪
Toast.makeText(MainActivity.this, "跟踪开始...", Toast.LENGTH_SHORT).show();
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.show();
}
//结束跟踪
private void endTrack() {
isTracking=false;//结束线程
Toast.makeText(this, "跟踪结束", Toast.LENGTH_SHORT).show();
//转化地址编码,把最后的经纬度转换成地址
geoCoder.reverseGeoCode(new ReverseGeoCodeOption().location(new LatLng(currentLat,currentLng)));
}
//跟踪回放
AlertDialog dialog=null;
private void trackBack() {
AlertDialog.Builder builder=new AlertDialog.Builder(this);
builder.setCancelable(false);
builder.setTitle("跟踪线路列表");
View view=getLayoutInflater().inflate(R.layout.track_line_playback_dialog,null);
ListView playbackListView=view.findViewById(R.id.listView1_play_back);
ArrayList> data=new ArrayList>();
ArrayList tracks=dbAdapter.getTracks();
HashMap map=null;
Track t=null;
for (int i=0;i();
t=tracks.get(i);
map.put("id",String.valueOf(t.getId()));
map.put("trackName_createDate",t.getTrack_name()+"---"+t.getCreate_date());
map.put("startEndLoc","从["+t.getStart_loc()+"]到["+t.getEnd_loc()+"]");
data.add(map);
}
SimpleAdapter adapter=new SimpleAdapter(this,data,R.layout.playback_item,new String[]{
"id","trackName_createDate","startEndLoc"},new int[]{
R.id.textView_id,R.id.textView_trackname,R.id.textView_startEndLoc});
playbackListView.setAdapter(adapter);
playbackListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
TextView tv_id=view.findViewById(R.id.textView_id);
int _id=Integer.parseInt(tv_id.getText().toString());
baiduMap.clear();
new Thread(new TrackPlaybackThread(_id)).start();
dialog.dismiss();
}
});
builder.setView(view);
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
list.clear();
dialog.dismiss();
}
});
dialog = builder.create();
dialog.show();
}
private boolean isTracking=false;
//用于存储两个相邻的经纬度点划线
private ArrayList list=new ArrayList();
//创建一条线路跟踪
private void createTrack(String trackName) {
Track track=new Track();
track.setTrack_name(trackName);
track.setCreate_date(DateUtils.toDate(new Date()));
track.setStart_loc(currentAddr);
currentTrackLineID=dbAdapter.addTrack(track);
dbAdapter.addTrackDetail(currentTrackLineID,currentLat,currentLng);
baiduMap.clear();
addOverlay();
list.add(new LatLng(currentLat,currentLng));
isTracking=true;//线程模拟的标记
Log.i("tag", String.valueOf(list));
new Thread(new TrackThread()).start();
}
//在地图上添加图层(线路的每一个点)
private void addOverlay() {
//添加一个标注覆盖物在当前位置
//构建Marker图标
baiduMap.setMyLocationEnabled(false);
BitmapDescriptor bitmap= BitmapDescriptorFactory.fromResource(android.R.drawable.star_on);
//构建MarkerOption,用于在地图上添加Marker
LatLng latLng=new LatLng(currentLat,currentLng);
OverlayOptions options=new MarkerOptions().position(latLng).icon(bitmap);
//在地图上添加Marker,并登录
baiduMap.addOverlay(options);
//把当前添加的位置作为地图中心点
baiduMap.animateMapStatus(MapStatusUpdateFactory.newLatLng(latLng));
}
//两个点之间划线
private void drawLine(){
OverlayOptions lineOptions=new PolylineOptions().points(list).color(0xFFFF0000);
baiduMap.addOverlay(lineOptions);
list.remove(0);
}
private class TrackPlaybackThread implements Runnable {
private int id;
public TrackPlaybackThread(int id) {
this.id=id;
}
@Override
public void run() {
ArrayList trackDetails=dbAdapter.getTrackDetails(id);
TrackDetail td=null;
list.clear();
currentLat=trackDetails.get(0).getLat();
currentLng=trackDetails.get(0).getLng();
list.add(new LatLng(currentLat,currentLng));
addOverlay();
for (int i = 0; i