Skip importing the Golden Map, import the package, and go directly to use
1. Use in Activity
1. Use mapview in layout
<com.amap.api.maps.MapView android:id="@+id/amapView" android:layout_width="match_parent" android:layout_height="0dp" android:background="#fff" android:clickable="true" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toBottomOf="@id/estimate_payment" />
2. Initialize the map in Actvity
Problems encountered:
(1) MapView.onCreate was not called in onCreate, resulting in a blank map
(2) MapView.OnPause is used in onPause, and MapView.OnResume is not used in onResume, causing the mapview to become stuck (neither moving the map nor zooming gestures work)
(3) Hide precision circles, zoom buttons, custom positioning bluespots ( https://lbs.amap.com/api/android-sdk/guide/interaction-with-map/control-interaction)
(4) Custom positioning button: Because Golden Map does not provide a way to replace the positioning button, you need to hide the positioning button of the original map, add a custom button, and perform the positioning after clicking.( http://lbsbbs.amap.com/forum.php?mod=viewthread&tid=14167)
Effect:
@InjectView(R.id.amapView) MapView mBmapView; //Declare AMapLocationClient class object private AMapLocationClient mLocationClient = null; //Declare AMapLocationClientOption object private AMapLocationClientOption mLocationOption = null; private AMap mAmap; private static final int MAP_ZOOM_SIZE = 18; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //Execute mMapView.onCreate(savedInstanceState) when activity executes onCreate to create a map mBmapView.onCreate(savedInstanceState); } @Override protected void onPause() { if (mBmapView != null) { //Execute mMapView.onPause () when activity executes onPause, suspending map drawing mBmapView.onPause(); } if (mLocationClient != null) { mLocationClient.stopLocation(); } super.onPause(); } @Override protected void onResume() { //Execute mMapView.onResume() when activity executes onResume, redraw the loaded map mBmapView.onResume(); if (mLocationClient != null) { mLocationClient.startLocation(); } super.onResume(); } @Override protected void onDestroy() { LogUtils.i("onDestroy"); clearRouteLines(); if (mLocationClient != null) { mLocationClient.stopLocation(); } if (mBmapView != null) { //Execute mMapView.onDestroy() when activity executes onDestroy, destroying the map mBmapView.onDestroy(); } super.onDestroy(); } @Override public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) { super.onSaveInstanceState(outState, outPersistentState); //Execute mMapView.onSaveInstanceState (outState) when activity executes onSaveInstanceState to save the current state of the map mBmapView.onSaveInstanceState(outState); } private void initMap() { if (mAmap == null) { mAmap = mBmapView.getMap(); } //Set the zoom level of the map you want to show CameraUpdate mCameraUpdate = CameraUpdateFactory.zoomTo(MAP_ZOOM_SIZE); mAmap.moveCamera(mCameraUpdate); //Custom positioning of bluespots: MyLocationStyle myLocationStyle = new MyLocationStyle(); myLocationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.drawable.location_indicator)); //Continuously locate and move your view to the center of the map, locating the bluespot and following the device.(position once a second) myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATE); //Set Precision Circle (Hide Precision Circle) myLocationStyle.strokeColor(Color.argb(0, 0, 0, 0)); myLocationStyle.radiusFillColor(Color.argb(0, 0, 0, 0)); //Hide Golden logo mAmap.getUiSettings().setLogoBottomMargin(-60); //Set Style to locate bluespots mAmap.setMyLocationStyle(myLocationStyle); //Initialize Location mLocationClient = new AMapLocationClient(getApplicationContext()); //Set Location Callback Listening mLocationClient.setLocationListener(this); //Initialize AMapLocationClientOption object mLocationOption = new AMapLocationClientOption(); //Set the positioning mode to AMapLocationMode.Hight_Accuracy, High Precision mode. mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy); //Get the highest accuracy results in the last 3 seconds: //Set the setOnceLocationLatest(boolean b) interface to true, and the SDK will return the highest accuracy results in the last 3 seconds when you start positioning. //If set to true, the setOnceLocation(boolean b) interface will also be set to true, otherwise it will not default to false. mLocationOption.setOnceLocationLatest(true); //Set whether to return address information (default return address information) mLocationOption.setNeedAddress(true); //Sets whether simulation locations are allowed, defaults to true, and allows simulation locations mLocationOption.setMockEnable(false); //Turn off caching mLocationOption.setLocationCacheEnable(false); mLocationClient.setLocationOption(mLocationOption); // Set to true to start showing positioning bluespots, false to hide positioning bluespots and not locate them, default is false mAmap.setMyLocationEnabled(true); //Hide the zoom button in the lower right corner mAmap.getUiSettings().setZoomControlsEnabled(false); //Set the default location button to not display, display the custom location button, and set the click event. mAmap.getUiSettings().setMyLocationButtonEnabled(false); //Start Location mLocationClient.startLocation(); }
Hide the positioning icon for the Gourde map:
//Set the default location button to not display, display the custom location button, and set the click event. mAmap.getUiSettings().setMyLocationButtonEnabled(false);
Set the icon's shaded attribute elevation (background s will take effect)
<ImageView android:id="@+id/im_location" android:layout_width="35dp" android:layout_height="35dp" android:layout_gravity="right" android:layout_margin="10dp" android:background="@drawable/roadrescue_location_btn_selector" android:clickable="true" android:elevation="2dp" android:scaleType="center" android:src="@drawable/location_btn" app:layout_constraintRight_toRightOf="parent" />
Set click events for custom positioning icons
@OnClick({R.id.im_location }) public void onViewClicked(View view) { switch (view.getId()) { case R.id.im_location: //Custom positioning control that moves to the positioning point, animateCamera animation effect, set the level of map zoom you want to show CameraUpdate mCameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, MAP_ZOOM_SIZE); mAmap.moveCamera(mCameraUpdate); break; } }
2. Use in Fragment s
Create maps in onCreateView, like any other Activity
@Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); mBmapView.onCreate(savedInstanceState); return mRootView; }
3. Route Planning
Given the starting point (available through onLocationChanged) and the ending point (such as the starting position of the drip driver), the route is drawn first, showing the user and driver markers.Then the longitude and latitude of the driver's position are obtained from the server by handler every minute, and the driver's marker position is redrawn, so it moves.
1. Draw path, start and end marker s
//Route Planning private RouteSearch mRouteSearch; //The purpose of this array is to put in all the coordinate points of the planned route for easy drawing. private ArrayList<LatLng> latLonArray = new ArrayList<>(); //Car smooth route, store two points private ArrayList<LatLng> runArray = new ArrayList<>(); //A marker that moves smoothly, that is, a cart private SmoothMoveMarker smoothMarker; /** * Given the driver's address, get the latitude and longitude of the driver's starting position (for not knowing the driver's latitude and longitude, knowing the driver's starting address) and the driving time, and draw a picture first * Road Map, Start and End * @param cityName */ private void getStoreLatlon(String cityName) { LogUtils.i("StoreyName;" + cityName); GeocodeSearch geocodeSearch = new GeocodeSearch(this); geocodeSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() { @Override public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int i) { } @Override public void onGeocodeSearched(GeocodeResult geocodeResult, int i) { if (i == 1000) { if (geocodeResult != null && geocodeResult.getGeocodeAddressList() != null && geocodeResult.getGeocodeAddressList().size() > 0) { GeocodeAddress geocodeAddress = geocodeResult.getGeocodeAddressList().get(0); double latitude = geocodeAddress.getLatLonPoint().getLatitude();//latitude double longititude = geocodeAddress.getLatLonPoint().getLongitude();//longitude mStoreLatlng = new LatLng(latitude, longititude); getStoreDriveTime(); LogUtils.i("lgq Geocoding:" + geocodeAddress.getAdcode() + ""); LogUtils.i("lgq latitude latitude:" + latitude + ""); LogUtils.i("lgq longitude longititude:" + longititude + ""); } else { ToastUtil.showMessage(RoadRescueApplyAct.this, "Place name error"); } } } }); GeocodeQuery geocodeQuery = new GeocodeQuery(cityName.trim(), "29"); geocodeSearch.getFromLocationNameAsyn(geocodeQuery); } /** *Query driver-to-user path */ private void getStoreDriveTime() { mRouteSearch = new RouteSearch(this); mRouteSearch.setRouteSearchListener(this); LatLng rescueLatlng = new LatLng(mCurrentRescueOrder.getLat(), mCurrentRescueOrder.getLng()); RouteSearch.FromAndTo fromAndTo = new RouteSearch.FromAndTo(convertToLatLonPoint(rescueLatlng), convertToLatLonPoint(mStoreLatlng)); RouteSearch.DriveRouteQuery routeQuery = new RouteSearch.DriveRouteQuery(fromAndTo, RouteSearch.DRIVING_SINGLE_AVOID_CONGESTION, null, null, ""); mRouteSearch.calculateDriveRouteAsyn(routeQuery); } //It goes to the callback method, chooses onDriveRouteSearched for processing, and stores all the latitude and longitude points of the path in the driverRouteResult @Override public void onDriveRouteSearched(DriveRouteResult driveRouteResult, int i) { LogUtils.i("i:" + i); if (i == 1000) { if (driveRouteResult == null) { LogUtils.e("driveResult is null"); } if (!latLonArray.isEmpty()) { latLonArray.clear(); } //Set estimated wait time LogUtils.i("time:" + driveRouteResult.getPaths().get(0).getDuration()); mDriveDuration = driveRouteResult.getPaths().get(0).getDuration(); mDistance = driveRouteResult.getPaths().get(0).getDistance(); Spanned durationText = Html .fromHtml(getString(R.string.roadrescue_duration, secondsToMinute(mDriveDuration))); mTvWaitTime.setText(durationText); //Set Distance Spanned distanceText = Html.fromHtml(getString(R.string.roadrescue_distance, meterToKilometer(mDistance))); mTvRescueDistance.setText(distanceText); //Do not draw a path map for work if (mCurrentRescueOrder.getStatus() == 1 || mCurrentRescueOrder.getStatus() == 2) { return; } for (DrivePath path : driveRouteResult.getPaths()) { for (DriveStep step : path.getSteps()) { for (LatLonPoint point : step.getPolyline()) { latLonArray.add(convertToLatLng(point)); } } } //Plan your route, draw your starting point, car, road map drawingRouteOverlay(latLonArray); //Use the change point as the starting point for smooth car in the future if (runArray.size() == 0) { runArray.add(mStoreLatlng); } showCarMarker(mStoreLatlng); } else { LogUtils.e("no route to find"); } } /** * Draw a route * @param drivePath */ private void drawingRouteOverlay(List<LatLng> drivePath) { this.startLatLng = drivePath.get(0); this.endLatLng = drivePath.get(drivePath.size() - 1); polyLineOptions = new PolylineOptions(); polyLineOptions.width(width); polyLineOptions.setCustomTexture(BitmapDescriptorFactory.fromResource(R.drawable.custtexture)); endBitmap = BitmapDescriptorFactory.fromResource(R.drawable.location_savecar); //Mark customer location on map as starting point addMarkerToMap(drivePath); //Draw a route drawLine(drivePath); } /** * Add marker s for start and end points to the map */ public void addMarkerToMap(List<LatLng> drivePath) { try { //Clear the original marker mAmap.clear(); //Add the user's location marker to the map LatLng rescueLatLng = new LatLng(mCurrentRescueOrder.getLat(), mCurrentRescueOrder.getLng()); endMarker = mAmap.addMarker(new MarkerOptions().position(rescueLatLng).icon(endBitmap)); } catch (Throwable throwable) { throwable.printStackTrace(); } } /** * Draw lines */ private void drawLine(List<LatLng> drivePath) { try { polyLineOptions.addAll(drivePath); allPolyLines.add(mAmap.addPolyline(polyLineOptions)); } catch (Throwable e) { e.printStackTrace(); } } //Show the driver's location private void showCarMarker(LatLng location) { zoomToSpan(); if (rescueCarMarker == null) { //If it's empty, the way to add a new icon is to set the positioning icon, which you can customize rescueCarMarker = mAmap.addMarker(new MarkerOptions().position(location) .icon(BitmapDescriptorFactory.fromResource(R.drawable.savecar))); } else { rescueCarMarker.setPosition(location); } } /** * Always keep points where they can be seen */ private void zoomToSpan() { try { LatLngBounds.Builder b = LatLngBounds.builder(); b.include(new LatLng(startLatLng.latitude, startLatLng.longitude)); b.include(new LatLng(endLatLng.latitude, endLatLng.longitude)); LatLngBounds bounds = b.build(); //This is the way to keep the vision in the middle, and see the Golden Map API in detail mAmap.animateCamera(CameraUpdateFactory.newLatLngBoundsRect(bounds, 100, 100, 100, 450)); } catch (Throwable e) { e.printStackTrace(); } }
2. Update driver marker location
//Get driver latitude and longitude from server every minute mHandler.sendEmptyMessageDelayed(MSG_UPDATE_RESCUE_CAR_LOCATION, UPDATE_RESCUE_CAR_LOCATION_INTERNAL);
private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { if (runArray == null) { return; }if (msg.what == MSG_UPDATE_RESCUE_CAR_LOCATION) { //Get Driver Location getRescueCarDistance(mCurrentRescueOrder.getOrderId()); sendEmptyMessageDelayed(MSG_UPDATE_RESCUE_CAR_LOCATION, UPDATE_RESCUE_CAR_LOCATION_INTERNAL); } } }; /** * Get driver position and calculate distance (out) * @param orderId */ private void getRescueCarDistance(long orderId) { RequestManager2.getServiceInstance() .getRescuevehicleLocation(orderId) .compose(RequestManager2.<LatLng> setSchedulers()) .subscribe(new BackgroundSubscriber<LatLng>(RoadRescueApplyAct.this) { @Override public void onSuccess(LatLng latLng) { super.onSuccess(latLng); LogUtils.e("rescuecar,latLng:" + latLng); //Get the distance between the store and the user, time calculated by map map LatLng rescueLatlng = new LatLng(mCurrentRescueOrder.getLat(), mCurrentRescueOrder.getLng()); mDistance = AMapUtils.calculateLineDistance(rescueLatlng, latLng); Spanned distanceText = Html .fromHtml(getString(R.string.roadrescue_distance, meterToKilometer(mDistance))); mTvRescueDistance.setText(distanceText); //Add Marker to show car location if (latLng.longitude == 0 || latLng.latitude == 0) { return; } //Update Car Location if (runArray.size() == 1) { //If there is only one point in runArray, get the latest car location and add another point runArray.add(latLng); } else if (runArray.size() == 2) { //If there are already two points in runArray, remove the first one and add the latest one runArray.remove(0); runArray.add(latLng); } if (smoothMarker != null) { smoothMarker.destroy(); } //Slide the car from runArray 0 to 1 showCarMarkerSmooth(); } }); } //Slide Cart private void showCarMarkerSmooth() { // Getting track coordinate points zoomToSpan(); if(rescueCarMarker!=null){ //Remove the car marker set at the beginning rescueCarMarker.remove(); } smoothMarker = new SmoothMoveMarker(mAmap); // Set Sliding Icon smoothMarker.setDescriptor(BitmapDescriptorFactory.fromResource(R.drawable.savecar)); LatLng drivePoint = runArray.get(0); Pair<Integer, LatLng> pair = SpatialRelationUtil.calShortestDistancePoint(runArray, drivePoint); runArray.set(pair.first, drivePoint); List<LatLng> subList = runArray.subList(pair.first, runArray.size()); // Setting Sliding Track Coordinate Points smoothMarker.setPoints(subList); // Set total sliding time 60s smoothMarker.setTotalDuration(60); // Start Sliding smoothMarker.startSmoothMove(); }
But the actual driver's location data may not be available, so we can simulate the driver's movement by choosing from all latitude and longitude points of the obtained route to simulate the driver continuing along the planned route.Define two ArrayList s, one for latLonArray to store all the points of the planned route, and one for runArray to store two points, constantly pulling points from latLonArray to simulate updating the driver's progress.(For example, the points in latLongArray are 0, 1, 2, 3, 4..., runArray updates data (0,1) (1,2) (2,3)...Then the car marker slides forward based on the two points inside runArray)
/** * Query routes based on latitude and longitude of start and end points */ private void startRouteSearch() { LogUtils.e("startRouteSearch"); mRouteSearch = new RouteSearch(this); mRouteSearch.setRouteSearchListener(this); RouteSearch.FromAndTo fromAndTo = new RouteSearch.FromAndTo(mStarPoint, mEndPoint); RouteSearch.DriveRouteQuery routeQuery = new RouteSearch.DriveRouteQuery(fromAndTo, RouteSearch.DRIVING_SINGLE_AVOID_CONGESTION, null, null, ""); mRouteSearch.calculateDriveRouteAsyn(routeQuery); } @Override public void onDriveRouteSearched(DriveRouteResult driveRouteResult, int i) { LogUtils.i("i:" + i); if (i == 1000) { if (driveRouteResult == null) { LogUtils.e("driveResult is null"); } if (!latLonArray.isEmpty()) { latLonArray.clear(); } for (DrivePath path : driveRouteResult.getPaths()) { for (DriveStep step : path.getSteps()) { for (LatLonPoint point : step.getPolyline()) { latLonArray.add(convertToLatLng(point)); } } } //Plan your route, draw your starting point, car, road map drawingRouteOverlay(latLonArray); runArray.add(latLonArray.get(0)); runArray.add(latLonArray.get(1)); showCarMarkerSmooth(); mHandler.sendEmptyMessage(MSG_UPDATE_CAR); } else { LogUtils.e("no route to find"); } } private void showCarMarkerSmooth() { zoomToSpan(); smoothMarker = new SmoothMoveMarker(mAmap); // Set Sliding Icon smoothMarker.setDescriptor(BitmapDescriptorFactory.fromResource(R.drawable.car)); LatLng drivePoint = runArray.get(0); Pair<Integer, LatLng> pair = SpatialRelationUtil.calShortestDistancePoint(runArray, drivePoint); runArray.set(pair.first, drivePoint); List<LatLng> subList = runArray.subList(pair.first, runArray.size()); // Setting Sliding Track Coordinate Points smoothMarker.setPoints(subList); // Set total sliding time smoothMarker.setTotalDuration(1); // Start Sliding smoothMarker.startSmoothMove(); } private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { if (runArray == null) { return; } if (msg.what == MSG_UPDATE_CAR) { if (latLonArray.size() > 2) { if (runArray.size() > 0) { runArray.remove(0); runArray.add(latLonArray.remove(0)); } else { runArray.add(latLonArray.remove(0)); runArray.add(latLonArray.remove(0)); } if (smoothMarker != null) { smoothMarker.destroy(); } showCarMarkerSmooth(); sendEmptyMessageDelayed(MSG_UPDATE_CAR, UPDATE_CAR_INTERNAL); } else { LogUtils.e("stop"); smoothMarker.stopMove(); clearRouteLines(); smoothMarker.destroy(); removeMessages(MSG_UPDATE_CAR); } } };