Android Baidu Map (1): Detailed introduction of sdk-type method parameters and positioning principle for Baidu Map positioning
Android Baidu Map (2): Baidu Location and Map Display Location Points
Source address https://github.com/zhuhao Happig/BaiduMapApi
The last article describes how to display location points on a map. This article mainly describes how to draw motion tracks on a map, and how to deal with click events on the map layer.
Many sports app s have the need to draw a runner's trajectory. For example, let's take a look at its rendering.
The effect to be achieved in this article
1. After running, draw the whole trajectory statically.
2. Drawing the track dynamically in the running process from time to time
How to achieve:
1. Connect dots to dots and draw line layers on MapView of Baidu Map.
2. Get the location point List < LatLng >: Obtain the location point through Baidu positioning sdk: Location Client class, and draw the locus of outdoor sports, which requires high accuracy of the location point, so we must use the position result of gps positioning type.
//Allow the use of gps positioning mOption.setOpenGps(true);
For more details on the sdk parameters of Baidu's positioning, please read the first article of Baidu Map (1)
A static drawing of the whole trajectory
1. Drawing Track
//Pseudo-code public void onCreate(){ // Map Initialization MapView mMapView = (MapView) findViewById(R.id.bmapView); BaiduMap mBaiduMap = mMapView.getMap(); // Open Location Layer mBaiduMap.setMyLocationEnabled(true); //Obtaining the Location Point after Motion coordinateConvert(); //Set the zoom midpoint LatLng target, and zoom ratio MapStatus.Builder builder = new MapStatus.Builder(); builder.target(target).zoom(18f); //Map Settings Zoom Status mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build())); /** * Configuration line segment layer parameter class: PolylineOptions * ooPolyline.width(13): line width * ooPolyline.color(0xAAFF0000): Line color red * ooPolyline.points(latLngs): List<LatLng> latLngs Location points, connecting adjacent points and points into a line becomes a trajectory. */ OverlayOptions ooPolyline = new PolylineOptions().width(13).color(0xAAFF0000).points(latLngs); //Draw a line layer on the map, mPolyline: line layer mPolyline = (Polyline) mBaiduMap.addOverlay(ooPolyline); mPolyline.setZIndex(3); }
/** * Here is the coordinate set Const. google wgs84 taken from google map, which is acquired after simulated motion. So we need to convert it into Baidu coordinates; in fact, we should add the location points returned by the positioning sdk into the location set. To locate the sdk, you need to set the return coordinate to Baidu coordinate: mOption.setCoorType("bd09ll"), so that it can be used directly without conversion. */ private void coordinateConvert(){ //Baidu Coordinate Converter Tool Class CoordinateConverter converter = new CoordinateConverter(); /** * Set the coordinate type to be transformed CoordType.COMMON: google The coordinates used in maps, Tencent maps and Gaode maps CoordType.GPS: Raw GPS coordinates acquired by equipment */ converter.from(CoordType.COMMON); double lanSum = 0; double lonSum = 0; for (int i = 0; i < Const.googleWGS84.length; i++) { //"39.881970,116.456218" String[] ll = Const.googleWGS84[i].split(","); LatLng sourceLatLng = new LatLng(Double.valueOf(ll[0]), Double.valueOf(ll[1])); converter.coord(sourceLatLng); //Coordinate points to be transformed LatLng desLatLng = converter.convert(); //Convert to Baidu coordinate point latLngs.add(desLatLng);//Join the set of locating points lanSum += desLatLng.latitude; lonSum += desLatLng.longitude; } //Here I set the zoom center of the map as all the geometric centers. target = new LatLng(lanSum/latLngs.size(), lonSum/latLngs.size()); }
Motion Trajectory Effect
2. Add Start Icon Layer, Click Layer to Response to Events
//Start Layer Icon BitmapDescriptor startBD= BitmapDescriptorFactory .fromResource(R.drawable.ic_me_history_startpoint); //Endpoint Layer Icon BitmapDescriptor finishBD= BitmapDescriptorFactory .fromResource(R.drawable.ic_me_history_finishpoint); //Display information window in map InfoWindow mInfoWindow; MarkerOptions oStart = new MarkerOptions();//Layer Parameter Configuration Class of Map Markup Type oStart.position(latLngs.get(0));//Layer position point, the first point is the starting point oStart.icon(startBD);//Setting Layer Pictures oStart.zIndex(1);//Setting Layer Index //Add Starting Layer Marker mMarkerA = (Marker) (mBaiduMap.addOverlay(oStart)); //Add Endpoint Layer MarkerOptions oFinish = new MarkerOptions().position(latLngs.get(latLngs.size()-1)).icon(finishBD).zIndex(2); Marker mMarkerB = (Marker) (mBaiduMap.addOverlay(oFinish)); //Setting Layer Click to Listen for Callbacks mBaiduMap.setOnMarkerClickListener(new OnMarkerClickListener() { public boolean onMarkerClick(final Marker marker) { if (marker.getZIndex() == mMarkerA.getZIndex() ) {//If it is the starting point layer TextView textView = new TextView(getApplicationContext()); textView.setText("Starting point"); textView.setTextColor(Color.BLACK); textView.setGravity(Gravity.CENTER); textView.setBackgroundResource(R.drawable.popup); //Setting Information Window Click Callback OnInfoWindowClickListener listener = new OnInfoWindowClickListener() { public void onInfoWindowClick() { //Here is the main thread, which can realize some of its own functions. Toast.makeText(getApplicationContext(),"Here is the starting point.", Toast.LENGTH_SHORT).show(); mBaiduMap.hideInfoWindow();//Hidden Information Window } }; LatLng latLng = marker.getPosition();//Location Points Displayed in Information Window /** * Construct an InfoWindow by passing in bitmap descriptor * bd - Display bitmap position - InfoWindow Displayed position points yOffset - The information window will overlap with the layer icon. Setting the offset of Y axis can solve this problem. listener - Click on the listener */ mInfoWindow = new InfoWindow(BitmapDescriptorFactory.fromView(textView), latLng, -47, listener); mBaiduMap.showInfoWindow(mInfoWindow);//Display information window } else if (marker.getZIndex() == mMarkerB.getZIndex()) {//If it's the endpoint layer Button button = new Button(getApplicationContext()); button.setText("End"); button.setOnClickListener(new OnClickListener() { public void onClick(View v) { Toast.makeText(getApplicationContext(),"This is the end point.", Toast.LENGTH_SHORT).show(); mBaiduMap.hideInfoWindow(); } }); LatLng latLng = marker.getPosition(); /** * An InfoWindow is constructed from the incoming view, which is used only to generate a Bitmap to plot on the map, and the listening event is implemented by itself. view - view on display position - Displayed geographic location yOffset - Y Axis offset */ mInfoWindow = new InfoWindow(button, latLng, -47); mBaiduMap.showInfoWindow(mInfoWindow); } return true; } }); //You can also add click events to the trajectory mBaiduMap.setOnPolylineClickListener(new BaiduMap.OnPolylineClickListener() { @Override public boolean onPolylineClick(Polyline polyline) { if (polyline.getZIndex() == mPolyline.getZIndex()) { Toast.makeText(getApplicationContext(),"Point:" + polyline.getPoints().size() + ",width:" + polyline.getWidth(), Toast.LENGTH_SHORT).show(); } return false; } });
Motion track effect, click icon to pop up information window
Click on the icon to pop up the information window to pop up Toast
At this point, the whole trajectory is drawn and the click event is added to the layer after the exercise.
Dynamically Drawing Motion Trajectories in Two Times
Time-to-time Dynamic Track Drawing Effect
The key lies in the point selection: the accuracy of some points returned by the gps just after receiving the signal is not high, which is easy to cause position offset. How to pick the point is very important.
//Pseudo-code public void onCreate() { mMapView = (MapView) findViewById(R.id.bmapView); mBaiduMap = mMapView.getMap(); // Open Location Layer mBaiduMap.setMyLocationEnabled(true); /**Add map zoom state change monitoring, when manually zooming in or out of the map, get the scaled proportion, and then get the next location. * Reset the zoom scale for the map, otherwise the map will revert to the default mCurrentZoom zoom scale */ mCurrentZoom = 18; mBaiduMap.setOnMapStatusChangeListener(new OnMapStatusChangeListener() { @Override public void onMapStatusChangeStart(MapStatus arg0) { } @Override public void onMapStatusChangeFinish(MapStatus arg0) { mCurrentZoom = arg0.zoom;//Get the value of the finger after zooming in the map } @Override public void onMapStatusChange(MapStatus arg0) { } }); //Set the location icon type to follow mode mBaiduMap.setMyLocationConfiguration(new MyLocationConfiguration( com.baidu.mapapi.map.MyLocationConfiguration.LocationMode.FOLLOWING, true, null)); // Location initialization mLocClient = new LocationClient(this); mLocClient.registerLocationListener(myListener); LocationClientOption option = new LocationClientOption(); option.setLocationMode(LocationMode.Device_Sensors);//Accept only gps location option.setOpenGps(true); // Allowing gps positioning option.setCoorType("bd09ll"); // Setting coordinate type option.setScanSpan(1000);//One gps per second mLocClient.setLocOption(option); } //Start to get the location point public void onStart() { start.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mLocClient != null && !mLocClient.isStarted()) { mLocClient.start(); } } }); } //Location callback is very important public class MyLocationListenner implements BDLocationListener { @Override public void onReceiveLocation(final BDLocation location) { if (location == null || mMapView == null) { return; } if (location.getLocType() == BDLocation.TypeGpsLocation) {//As long as the gps point if (isFirstLoc) {//First positioning /**The first point is very important, which determines the effect of the trajectory. The accuracy of some points returned by the gps just after receiving the signal is not high. * Choose a starting point with relatively high accuracy as far as possible. This process can be completed in about 5-10 seconds after receiving the signal from the gps, without affecting the effect. * Note: gps receives satellite signals in less than ten seconds and more than a few minutes. * If the mobile phone can not receive the gps for a long time, quit, restart the mobile phone and try again, this is the hardware reason. */ LatLng ll = null; //Choose a starting point with relatively high accuracy ll = getMostAccuracyLocation(location); if(ll == null){ return; } isFirstLoc = false; points.add(ll);//Join the collection last = ll; //Display the current location point and zoom the map locateAndZoom(location, ll); //Mark the Start Layer Location MarkerOptions oStart = new MarkerOptions();// Map Marker Cover Parameter Configuration Class oStart.position(points.get(0));// Cover location point, the first point is the starting point oStart.icon(startBD);// Setting Cover Pictures mBaiduMap.addOverlay(oStart); // Add this layer to the map return;//Draw a trajectory with at least two points, and you can return from the first location. } //Start with the second point LatLng ll = new LatLng(location.getLatitude(), location.getLongitude()); //The frequency of sdk callback to gps position is 1 second, and the dynamic drawing of position points is not very obvious. It can be set that the distance between points is more than 5 meters before adding to the set. if (DistanceUtil.getDistance(last, ll) < 5) { return; } points.add(ll);//If you want to draw the whole trajectory after the motion is completed, the position points are in this set. last = ll; //Display the current location point and zoom the map locateAndZoom(location, ll); //Clear the last trajectory to avoid overlapping paintings mMapView.getMap().clear(); //Starting point layers will also be cleared and redrawn MarkerOptions oStart = new MarkerOptions(); oStart.position(points.get(0)); oStart.icon(startBD); mBaiduMap.addOverlay(oStart); //Draw a trajectory line layer of points in the points set and display it on the map OverlayOptions ooPolyline = new PolylineOptions().width(13).color(0xAAFF0000).points(points); mPolyline = (Polyline) mBaiduMap.addOverlay(ooPolyline); } } } //First positioning is very important. Choose a starting point with relatively high accuracy. private LatLng getMostAccuracyLocation(final BDLocation location){ if (location.getRadius()>25) {//Direct abandonment of points with position accuracy greater than 25 meters return null; } LatLng ll = new LatLng(location.getLatitude(), location.getLongitude()); if (DistanceUtil.getDistance(last, ll ) > 5) { last = ll; points.clear();//There are two points greater than 5, come back. return null; } points.add(ll); last = ll; //The distance between five consecutive points is less than 5. It is considered that the gps is stable and the latest point is the starting point. if(points.size() >= 5){ points.clear(); return ll; } return null; } //Display the current location point and zoom the map private void locateAndZoom(BDLocation location, LatLng ll) { /** * Record the current latitude and longitude. When the position is unchanged, the mobile phone rotates to get the direction of the direction sensor. Reset the location parameters of the map to make the map arrow rotate with the mobile phone in the following mode */ mCurrentLat = location.getLatitude(); mCurrentLon = location.getLongitude(); locData = new MyLocationData.Builder().accuracy(0)//Remove the precision circle //This mCurrentDirection obtains the orientation information of the mobile phone sensor for itself, clockwise 0-360 .direction(mCurrentDirection).latitude(location.getLatitude()) .longitude(location.getLongitude()).build(); mBaiduMap.setMyLocationData(locData);//Display the current location point //Set zoom centers and zoom scale values for maps builder = new MapStatus.Builder(); builder.target(ll).zoom(mCurrentZoom); mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build())); } //End of Exercise Add End Icon finish.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mLocClient != null && mLocClient.isStarted()) { mLocClient.stop();//Stop positioning if(points.size() <= 0){ return; } //Remember to mark the end point icon at the end of the exercise MarkerOptions oFinish = new MarkerOptions(); oFinish.position(points.get(points.size() - 1)); oFinish.icon(finishBD); mBaiduMap.addOverlay(oFinish); } } });
Exit and Release Resources
//Pseudo-code protected void onDestroy() { // Destruction Location at Exit mLocClient.unRegisterLocationListener(myListener); mLocClient.stop(); // Close the Location Layer mBaiduMap.setMyLocationEnabled(false); mMapView.getMap().clear(); mMapView.onDestroy(); mMapView = null; startBD.recycle(); finishBD.recycle(); }
Note: When we draw the motion trajectory, we need to locate the position returned by the sdk with high accuracy, so the effect of the trajectory will be better. Therefore, we must accept the position points of the gps. But the accuracy of the position of the GPS is not high when the signal is received at the beginning, and the position drift will occur, so we need to select a point with better accuracy. In buildings, bridges, trees and tunnels, the GPS signal is not good and the accuracy is not high, so in the open area, the trajectory effect is better.
For more details on Baidu Map and Location sdk parameters, please read the first and second articles of Baidu Map.
The above article is a summary of my work for your reference. Please correct any mistakes.