需要源码请点赞关注收藏后评论区留言~~~
一、获取地点信息
至于如何集成腾讯地图和调用腾讯地图接口此处不再赘述,有需要请参见我之前的博客
腾讯地图用来搜索POI地点的工具是TencentSearch,通过它查询POI主要分为下列四个步骤: (1)创建一个腾讯搜索对象TencentSearch;
(2)区分条件构建搜索类型;
(3)按照搜索类型和关键词构建搜索参数SearchParam,并设置搜索结果的分页大小和检索页码;
(4)调用腾讯搜索对象的search方法,根据搜索参数查找符合条件的地点列表。
运行测试App效果如下 可以自行定义终点
代码如下
Java类
package com.example.location;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import com.example.location.util.MapTencentUtil;
import com.tencent.lbssearch.TencentSearch;
import com.tencent.lbssearch.httpresponse.BaseObject;
import com.tencent.lbssearch.httpresponse.HttpResponseListener;
import com.tencent.lbssearch.object.param.SearchParam;
import com.tencent.lbssearch.object.result.SearchResultObject;
import com.tencent.map.geolocation.TencentLocation;
import com.tencent.map.geolocation.TencentLocationListener;
import com.tencent.map.geolocation.TencentLocationManager;
import com.tencent.map.geolocation.TencentLocationRequest;
import com.tencent.tencentmap.mapsdk.maps.CameraUpdate;
import com.tencent.tencentmap.mapsdk.maps.CameraUpdateFactory;
import com.tencent.tencentmap.mapsdk.maps.MapView;
import com.tencent.tencentmap.mapsdk.maps.TencentMap;
import com.tencent.tencentmap.mapsdk.maps.model.BitmapDescriptor;
import com.tencent.tencentmap.mapsdk.maps.model.BitmapDescriptorFactory;
import com.tencent.tencentmap.mapsdk.maps.model.LatLng;
import com.tencent.tencentmap.mapsdk.maps.model.Marker;
import com.tencent.tencentmap.mapsdk.maps.model.MarkerOptions;
import com.tencent.tencentmap.mapsdk.maps.model.PolygonOptions;
import com.tencent.tencentmap.mapsdk.maps.model.PolylineOptions;
import java.util.ArrayList;
import java.util.List;
public class MapSearchActivity extends AppCompatActivity
implements TencentLocationListener, TencentMap.OnMapClickListener {
private final static String TAG = "MapSearchActivity";
private TextView tv_scope_desc; // 声明一个文本视图对象
private EditText et_searchkey; // 声明一个编辑框对象
private EditText et_city; // 声明一个编辑框对象
private int mSearchMethod; // 搜索类型
private String[] mSearchArray = {"搜城市", "搜周边"};
private int SEARCH_CITY = 0; // 搜城市
private int SEARCH_NEARBY = 1; // 搜周边
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map_search);
initView(); // 初始化视图
initMethodSpinner(); // 初始化搜索方式下拉框
initLocation(); // 初始化定位服务
initSearch(); // 初始化搜索服务
}
// 初始化视图
private void initView() {
tv_scope_desc = findViewById(R.id.tv_scope_desc);
et_city = findViewById(R.id.et_city);
et_searchkey = findViewById(R.id.et_searchkey);
findViewById(R.id.btn_clear_data).setOnClickListener(v -> {
et_city.setText("");
et_searchkey.setText("");
mTencentMap.clearAllOverlays(); // 清除所有覆盖物
mPosList.clear();
isPolygon = false;
});
}
// 初始化搜索方式下拉框
private void initMethodSpinner() {
Spinner sp_method = findViewById(R.id.sp_method);
ArrayAdapter<String> county_adapter = new ArrayAdapter<>(this,
R.layout.item_select, mSearchArray);
sp_method.setPrompt("请选择POI搜索方式");
sp_method.setAdapter(county_adapter);
sp_method.setOnItemSelectedListener(new MethodSelectedListener());
sp_method.setSelection(0);
}
class MethodSelectedListener implements AdapterView.OnItemSelectedListener {
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
mSearchMethod = arg2;
if (mSearchMethod == SEARCH_CITY) {
tv_scope_desc.setText("市内找");
} else if (mSearchMethod == SEARCH_NEARBY) {
tv_scope_desc.setText("米内找");
}
et_city.setText("");
et_searchkey.setText("");
}
public void onNothingSelected(AdapterView<?> arg0) {}
}
// 以下是定位代码
private TencentLocationManager mLocationManager; // 声明一个腾讯定位管理器对象
private MapView mMapView; // 声明一个地图视图对象
private TencentMap mTencentMap; // 声明一个腾讯地图对象
private boolean isFirstLoc = true; // 是否首次定位
private LatLng mLatLng; // 当前位置的经纬度
// 初始化定位服务
private void initLocation() {
mMapView = findViewById(R.id.mapView);
mTencentMap = mMapView.getMap(); // 获取腾讯地图对象
mTencentMap.setOnMapClickListener(this); // 设置地图的点击监听器
mLocationManager = TencentLocationManager.getInstance(this);
// 创建腾讯定位请求对象
TencentLocationRequest request = TencentLocationRequest.create();
request.setInterval(30000).setAllowGPS(true);
request.setRequestLevel(TencentLocationRequest.REQUEST_LEVEL_ADMIN_AREA);
mLocationManager.requestLocationUpdates(request, this); // 开始定位监听
}
@Override
public void onLocationChanged(TencentLocation location, int resultCode, String resultDesc) {
if (resultCode == TencentLocation.ERROR_OK) { // 定位成功
if (location != null && isFirstLoc) { // 首次定位
isFirstLoc = false;
// 创建一个经纬度对象
mLatLng = new LatLng(location.getLatitude(), location.getLongitude());
CameraUpdate update = CameraUpdateFactory.newLatLngZoom(mLatLng, 12);
mTencentMap.moveCamera(update); // 把相机视角移动到指定地点
// 从指定图片中获取位图描述
BitmapDescriptor bitmapDesc = BitmapDescriptorFactory
.fromResource(R.drawable.icon_locate);
MarkerOptions ooMarker = new MarkerOptions(mLatLng).draggable(false) // 不可拖动
.visible(true).icon(bitmapDesc).snippet("这是您的当前位置");
mTencentMap.addMarker(ooMarker); // 往地图添加标记
}
} else { // 定位失败
Log.d(TAG, "定位失败,错误代码为"+resultCode+",错误描述为"+resultDesc);
}
}
@Override
public void onStatusUpdate(String s, int i, String s1) {}
@Override
protected void onStart() {
super.onStart();
mMapView.onStart();
}
@Override
protected void onStop() {
super.onStop();
mMapView.onStop();
}
@Override
public void onPause() {
super.onPause();
mMapView.onPause();
}
@Override
public void onResume() {
super.onResume();
mMapView.onResume();
}
@Override
protected void onDestroy() {
super.onDestroy();
mLocationManager.removeUpdates(this); // 移除定位监听
mMapView.onDestroy();
}
// 以下是POI搜索代码
private TencentSearch mTencentSearch; // 声明一个腾讯搜索对象
private int mLoadIndex = 1; // 搜索结果的第几页
// 初始化搜索服务
private void initSearch() {
// 创建一个腾讯搜索对象
mTencentSearch = new TencentSearch(this);
findViewById(R.id.btn_search).setOnClickListener(v -> searchPoi());
findViewById(R.id.btn_next_data).setOnClickListener(v -> {
mLoadIndex++;
mTencentMap.clearAllOverlays(); // 清除所有覆盖物
searchPoi(); // 搜索指定的地点列表
});
}
// 搜索指定的地点列表
public void searchPoi() {
Log.d(TAG, "editCity=" + et_city.getText().toString()
+ ", editSearchKey=" + et_searchkey.getText().toString()
+ ", mLoadIndex=" + mLoadIndex);
String keyword = et_searchkey.getText().toString();
String value = et_city.getText().toString();
SearchParam searchParam = new SearchParam();
if (mSearchMethod == SEARCH_CITY) { // 城市搜索
SearchParam.Region region = new SearchParam
.Region(value) // 设置搜索城市
.autoExtend(false); // 设置搜索范围不扩大
searchParam = new SearchParam(keyword, region); // 构建地点检索
} else if (mSearchMethod == SEARCH_NEARBY) { // 周边搜索
int radius = Integer.parseInt(value);
SearchParam.Nearby nearby = new SearchParam
.Nearby(mLatLng, radius).autoExtend(false); // 不扩大搜索范围
searchParam = new SearchParam(keyword, nearby); // 构建地点检索
}
searchParam.pageSize(10); // 每页大小
searchParam.pageIndex(mLoadIndex); // 第几页
// 根据搜索参数查找符合条件的地点列表
mTencentSearch.search(searchParam, new HttpResponseListener<BaseObject>() {
@Override
public void onFailure(int arg0, String arg2, Throwable arg3) {
Toast.makeText(getApplicationContext(), arg2, Toast.LENGTH_LONG).show();
}
@Override
public void onSuccess(int arg0, BaseObject arg1) {
if (arg1 == null) {
return;
}
SearchResultObject obj = (SearchResultObject) arg1;
if(obj.data==null || obj.data.size()==0){
return;
}
// 将地图中心坐标移动到检索到的第一个地点
CameraUpdate update = CameraUpdateFactory.newLatLngZoom(obj.data.get(0).latLng, 12);
mTencentMap.moveCamera(update); // 把相机视角移动到指定地点
// 将其他检索到的地点在地图上用 marker 标出来
for (SearchResultObject.SearchResultData data : obj.data){
Log.d(TAG,"title:"+data.title + ";" + data.address);
// 往地图添加标记
mTencentMap.addMarker(new MarkerOptions(data.latLng)
.title(data.title).snippet(data.address));
}
}
});
}
// 下面是绘图代码
private int lineColor = 0x55FF0000;
private int textColor = 0x990000FF;
private int polygonColor = 0x77FFFF00;
private int radiusLimit = 100;
private List<LatLng> mPosList = new ArrayList<>();
private boolean isPolygon = false;
// 往地图上添加一个点
private void addDot(LatLng pos) {
if (isPolygon) {
mPosList.clear();
isPolygon = false;
}
boolean isFirst = false;
LatLng thisPos = pos;
if (mPosList.size() > 0) {
LatLng firstPos = mPosList.get(0);
int distance = (int) Math.round(MapTencentUtil.getShortDistance(
thisPos.longitude, thisPos.latitude,
firstPos.longitude, firstPos.latitude));
if (mPosList.size() == 1 && distance <= 0) { // 多次点击起点,要忽略之
return;
} else if (mPosList.size() > 1) {
LatLng lastPos = mPosList.get(mPosList.size() - 1);
int lastDistance = (int) Math.round(MapTencentUtil.getShortDistance(
thisPos.longitude, thisPos.latitude,
lastPos.longitude, lastPos.latitude));
if (lastDistance <= 0) { // 重复响应当前位置的点击,要忽略之
return;
}
}
if (distance < radiusLimit * 2) {
thisPos = firstPos;
isFirst = true;
}
Log.d(TAG, "distance=" + distance + ", radiusLimit=" + radiusLimit + ", isFirst=" + isFirst);
// 画直线
LatLng lastPos = mPosList.get(mPosList.size() - 1);
List<LatLng> pointList = new ArrayList<>();
pointList.add(lastPos);
pointList.add(thisPos);
PolylineOptions ooPolyline = new PolylineOptions().width(2)
.color(lineColor).addAll(pointList);
// 下面计算两点之间距离
distance = (int) Math.round(MapTencentUtil.getShortDistance(
thisPos.longitude, thisPos.latitude,
lastPos.longitude, lastPos.latitude));
String disText;
if (distance > 1000) {
disText = Math.round(distance * 10 / 1000) / 10d + "公里";
} else {
disText = distance + "米";
}
PolylineOptions.SegmentText segment = new PolylineOptions.SegmentText(0, 1, disText);
PolylineOptions.Text text = new PolylineOptions.Text.Builder(segment)
.color(textColor).size(15).build();
ooPolyline.text(text);
mTencentMap.addPolyline(ooPolyline); // 往地图上添加一组连线
}
if (!isFirst) {
// 从指定图片中获取位图描述
BitmapDescriptor bitmapDesc = BitmapDescriptorFactory.fromResource(R.drawable.icon_geo);
MarkerOptions ooMarker = new MarkerOptions(thisPos).draggable(false) // 不可拖动
.visible(true).icon(bitmapDesc);
mTencentMap.addMarker(ooMarker); // 往地图添加标记
// 设置地图标记的点击监听器
mTencentMap.setOnMarkerClickListener(marker -> {
LatLng markPos = marker.getPosition();
addDot(markPos); // 往地图上添加一个点
marker.showInfoWindow(); // 显示标记的信息窗口
return true;
});
} else {
if (mPosList.size() < 3) { // 可能存在地图与标记同时响应点击事件的情况
mPosList.clear();
isPolygon = false;
return;
}
// 画多边形
PolygonOptions ooPolygon = new PolygonOptions().addAll(mPosList)
.strokeColor(0xFF00FF00).strokeWidth(3)
.fillColor(polygonColor);
mTencentMap.addPolygon(ooPolygon); // 往地图上添加多边形
isPolygon = true;
}
mPosList.add(thisPos);
}
@Override
public void onMapClick(LatLng arg0) {
addDot(arg0); // 往地图上添加一个点
}
}
二、规划导航线路
腾讯地图导航功能的使用过程主要分成下列两个步骤:
(1)区分条件构建出行参数
1)准备步行的话,要构建步行参数WalkingParam;
2)准备驾车的话,要构建驾驶参数DrivingParam。
(2)创建一个腾讯搜索对象,再调用搜索对象的getRoutePlan方法,根据出行参数规划导航路线。
演示视频如下 为动态动画
Android导航路线动态图
随着时间的推移 地图上的图标会自行移动向目的的
代码如下
Java类
package com.example.location;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.RadioGroup;
import android.widget.Toast;
import com.tencent.lbssearch.TencentSearch;
import com.tencent.lbssearch.httpresponse.HttpResponseListener;
import com.tencent.lbssearch.object.param.DrivingParam;
import com.tencent.lbssearch.object.param.WalkingParam;
import com.tencent.lbssearch.object.result.DrivingResultObject;
import com.tencent.lbssearch.object.result.WalkingResultObject;
import com.tencent.map.geolocation.TencentLocation;
import com.tencent.map.geolocation.TencentLocationListener;
import com.tencent.map.geolocation.TencentLocationManager;
import com.tencent.map.geolocation.TencentLocationRequest;
import com.tencent.tencentmap.mapsdk.maps.CameraUpdate;
import com.tencent.tencentmap.mapsdk.maps.CameraUpdateFactory;
import com.tencent.tencentmap.mapsdk.maps.MapView;
import com.tencent.tencentmap.mapsdk.maps.TencentMap;
import com.tencent.tencentmap.mapsdk.maps.model.BitmapDescriptor;
import com.tencent.tencentmap.mapsdk.maps.model.BitmapDescriptorFactory;
import com.tencent.tencentmap.mapsdk.maps.model.LatLng;
import com.tencent.tencentmap.mapsdk.maps.model.LatLngBounds;
import com.tencent.tencentmap.mapsdk.maps.model.Marker;
import com.tencent.tencentmap.mapsdk.maps.model.MarkerOptions;
import com.tencent.tencentmap.mapsdk.maps.model.PolylineOptions;
import com.tencent.tencentmap.mapsdk.vector.utils.animation.MarkerTranslateAnimator;
import java.util.ArrayList;
import java.util.List;
public class MapNavigationActivity extends AppCompatActivity
implements TencentLocationListener, TencentMap.OnMapClickListener {
private final static String TAG = "MapNavigationActivity";
private RadioGroup rg_type; // 声明一个单选组对象
private TencentLocationManager mLocationManager; // 声明一个腾讯定位管理器对象
private MapView mMapView; // 声明一个地图视图对象
private TencentMap mTencentMap; // 声明一个腾讯地图对象
private boolean isFirstLoc = true; // 是否首次定位
private LatLng mMyPos; // 当前的经纬度
private List<LatLng> mPosList = new ArrayList<>(); // 起点和终点
private List<LatLng> mRouteList = new ArrayList<>(); // 导航路线列表
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map_navigation);
initLocation(); // 初始化定位服务
initView(); // 初始化视图
}
// 初始化视图
private void initView() {
rg_type = findViewById(R.id.rg_type);
rg_type.setOnCheckedChangeListener((group, checkedId) -> showRoute());
findViewById(R.id.btn_start).setOnClickListener(v -> {
if (mPosList.size() < 2) {
Toast.makeText(this, "请选中起点和终点后再出发", Toast.LENGTH_SHORT).show();
} else {
playDriveAnim(); // 播放行驶过程动画
}
});
findViewById(R.id.btn_reset).setOnClickListener(v -> {
mTencentMap.clearAllOverlays(); // 清除所有覆盖物
mPosList.clear();
mRouteList.clear();
showMyMarker(); // 显示我的位置标记
});
}
private Marker mMarker; // 声明一个小车标记
// 播放行驶过程动画
private void playDriveAnim() {
if (mPosList.size() < 2) {
return;
}
if (mMarker != null) {
mMarker.remove(); // 移除地图标记
}
// 从指定图片中获取位图描述
BitmapDescriptor bitmapDesc = BitmapDescriptorFactory.fromResource(R.drawable.car);
MarkerOptions ooMarker = new MarkerOptions(mRouteList.get(0))
.anchor(0.5f, 0.5f).icon(bitmapDesc).flat(true).clockwise(false);
mMarker = mTencentMap.addMarker(ooMarker); // 往地图添加标记
LatLng[] routeArray = mRouteList.toArray(new LatLng[mRouteList.size()]);
// 创建平移动画
MarkerTranslateAnimator anim = new MarkerTranslateAnimator(mMarker, 50 * 1000, routeArray, true);
// 动态调整相机视角
mTencentMap.animateCamera(CameraUpdateFactory.newLatLngBounds(
LatLngBounds.builder().include(mRouteList).build(), 50));
anim.startAnimation(); // 开始播放动画
}
// 初始化定位服务
private void initLocation() {
mMapView = findViewById(R.id.mapView);
mTencentMap = mMapView.getMap(); // 获取腾讯地图对象
mTencentMap.setOnMapClickListener(this); // 设置地图的点击监听器
mLocationManager = TencentLocationManager.getInstance(this);
// 创建腾讯定位请求对象
TencentLocationRequest request = TencentLocationRequest.create();
request.setInterval(30000).setAllowGPS(true);
request.setRequestLevel(TencentLocationRequest.REQUEST_LEVEL_ADMIN_AREA);
mLocationManager.requestLocationUpdates(request, this); // 开始定位监听
}
// 显示我的位置标记
private void showMyMarker() {
CameraUpdate update = CameraUpdateFactory.newLatLngZoom(mMyPos, 12);
mTencentMap.moveCamera(update); // 把相机视角移动到指定地点
showPosMarker(mMyPos, R.drawable.icon_locate, "这是您的当前位置"); // 显示位置标记
}
// 显示位置标记
private void showPosMarker(LatLng latLng, int imageId, String desc) {
// 从指定图片中获取位图描述
BitmapDescriptor bitmapDesc = BitmapDescriptorFactory.fromResource(imageId);
MarkerOptions ooMarker = new MarkerOptions(latLng).draggable(false) // 不可拖动
.visible(true).icon(bitmapDesc).snippet(desc);
mTencentMap.addMarker(ooMarker); // 往地图添加标记
}
@Override
public void onLocationChanged(TencentLocation location, int resultCode, String resultDesc) {
if (resultCode == TencentLocation.ERROR_OK) { // 定位成功
if (location != null && isFirstLoc) { // 首次定位
isFirstLoc = false;
// 创建一个经纬度对象
mMyPos = new LatLng(location.getLatitude(), location.getLongitude());
showMyMarker(); // 显示我的位置标记
}
} else { // 定位失败
Log.d(TAG, "定位失败,错误代码为"+resultCode+",错误描述为"+resultDesc);
}
}
@Override
public void onStatusUpdate(String s, int i, String s1) {}
@Override
public void onMapClick(LatLng latLng) {
mPosList.add(latLng);
if (mPosList.size() == 1) {
showPosMarker(latLng, R.drawable.icon_geo, "起点"); // 显示位置标记
}
showRoute(); // 展示导航路线
}
// 展示导航路线
private void showRoute() {
if (mPosList.size() >= 2) {
mRouteList.clear();
LatLng beginPos = mPosList.get(0); // 获取起点
LatLng endPos = mPosList.get(mPosList.size()-1); // 获取终点
mTencentMap.clearAllOverlays(); // 清除所有覆盖物
showPosMarker(beginPos, R.drawable.icon_geo, "起点"); // 显示位置标记
showPosMarker(endPos, R.drawable.icon_geo, "终点"); // 显示位置标记
if (rg_type.getCheckedRadioButtonId() == R.id.rb_walk) {
getWalkingRoute(beginPos, endPos); // 规划步行导航
} else {
getDrivingRoute(beginPos, endPos); // 规划行车导航
}
}
}
// 规划步行导航
private void getWalkingRoute(LatLng beginPos, LatLng endPos) {
WalkingParam walkingParam = new WalkingParam();
walkingParam.from(beginPos); // 指定步行的起点
walkingParam.to(endPos); // 指定步行的终点
// 创建一个腾讯搜索对象
TencentSearch tencentSearch = new TencentSearch(getApplicationContext());
Log.d(TAG, "checkParams:" + walkingParam.checkParams());
// 根据步行参数规划导航路线
tencentSearch.getRoutePlan(walkingParam, new HttpResponseListener<WalkingResultObject>() {
@Override
public void onSuccess(int statusCode, WalkingResultObject object) {
if (object==null || object.result==null || object.result.routes==null) {
Log.d(TAG, "导航路线为空");
return;
}
Log.d(TAG, "message:" + object.message);
for (WalkingResultObject.Route result : object.result.routes) {
mRouteList.addAll(result.polyline);
// 往地图上添加一组连线
mTencentMap.addPolyline(new PolylineOptions().addAll(mRouteList)
.color(0x880000ff).width(20));
}
}
@Override
public void onFailure(int statusCode, String responseString, Throwable throwable) {
Log.d(TAG, statusCode + " " + responseString);
}
});
}
// 规划行车导航
private void getDrivingRoute(LatLng beginPos, LatLng endPos) {
// 创建导航参数
DrivingParam drivingParam = new DrivingParam(beginPos, endPos);
// 指定道路类型为主路
drivingParam.roadType(DrivingParam.RoadType.ON_MAIN_ROAD);
drivingParam.heading(90); // 起点位置的车头方向
drivingParam.accuracy(5); // 行车导航的精度,单位米
// 创建一个腾讯搜索对象
TencentSearch tencentSearch = new TencentSearch(this);
// 根据行车参数规划导航路线
tencentSearch.getRoutePlan(drivingParam, new HttpResponseListener<DrivingResultObject>() {
@Override
public void onSuccess(int statusCode, DrivingResultObject object) {
if (object==null || object.result==null || object.result.routes==null) {
Log.d(TAG, "导航路线为空");
return;
}
Log.d(TAG, "message:" + object.message);
for (DrivingResultObject.Route route : object.result.routes){
mRouteList.addAll(route.polyline);
// 往地图上添加一组连线
mTencentMap.addPolyline(new PolylineOptions().addAll(mRouteList)
.color(0x880000ff).width(20));
}
}
@Override
public void onFailure(int statusCode, String responseString, Throwable throwable) {
Log.d(TAG, statusCode + " " + responseString);
}
});
}
@Override
protected void onStart() {
super.onStart();
mMapView.onStart();
}
@Override
protected void onStop() {
super.onStop();
mMapView.onStop();
}
@Override
public void onPause() {
super.onPause();
mMapView.onPause();
}
@Override
public void onResume() {
super.onResume();
mMapView.onResume();
}
@Override
protected void onDestroy() {
super.onDestroy();
mLocationManager.removeUpdates(this); // 移除定位监听
mMapView.onDestroy();
}
}
创作不易 觉得有帮助请点赞关注收藏~~~