基于Google提供play-services:9.8.0的Google 地图开发,适用于Activity、Fragment,并实现添加Marker和根据经纬度显示运动轨迹

时间:2022-05-24 18:18:54

本文是基利用Google提供play-services:9.8.0的Google 地图开发,适用于Activity、Fragment中添加google地图,并实现添加Marker和根据经纬度显示运动轨迹;

新版本的google地图开发,已经没有MapView和MapControler等实现地图的操作。

在Activity中的layout中xml是:

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:map="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.ilang.googlemaptest.MapsActivity" />

Activity中onResume,onPause,onDestroy等可以调用SupportMapFragment的onResume,onPause,onDestroy。


在Fragment中的layout中xml是:

<com.google.android.gms.maps.MapView
        android:id="@+id/mv_google"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

Fragment中onResume,onPause,onDestroy等可以调用MapView的onResume,onPause,onDestroy。


AndroidManifest.xml添加网络和位置权限

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.LOCATION_HARDWARE" />

<uses-feature android:name="android.hardware.Sensor" />

application中申明

<meta-data  android:name="com.google.android.geo.API_KEY"  android:value="@string/google_maps_key" />
 

利用自己编写的一个GoogleMap工具类实现根据经纬度,在Google Map显示图标和运动轨迹,调用接口为setMarkerOnPosition(LatLng latlng)和

showRouteOnMap(LatLng[] latLngs)。
 
该工具栏有三个initMap方法,前两个是用于Activity中调用,后一个是把MapView放到Fragment中使用时的初始化google地图方法。
 
下文是完整的GoogleMap工具类代码:
 
 
public class GoogleMapHelper implements OnMapReadyCallback {

    private final String TAG = this.getClass().getSimpleName();

    private Context mContext = null;
    private GoogleMap map = null;
    private Location mLocation = null;
    private SupportMapFragment mapFragment = null;
    private Marker marker = null;
    private LatLng[] latLngs = null;

    /**
     * this method will be used in activity
     *
     * @param context
     * @param resId
     */
    public void initMap(Context context, int resId) {
        if (context != null) {
            mapFragment = (SupportMapFragment) ((FragmentActivity) context)
                    .getSupportFragmentManager()
                    .findFragmentById(resId);
            mContext = context;
            if (mapFragment != null) {
                mapFragment.getMapAsync(this);
            }
        }
    }

    /**
     * this method will be used in activity
     *
     * @param fragment
     */
    public void initMap(SupportMapFragment fragment) {
        if (fragment != null) {
            mapFragment = fragment;
            mapFragment.getMapAsync(this);
        }
    }

    /**
     * this method will be used in fragment
     *
     * @param mapView ,google MapView
     */
    public void initMap(Context context, MapView mapView, Bundle savedInstanceState) {
        if (mapView != null) {
            mapView.onCreate(savedInstanceState);
            //mapView.onResume();    // It will get the map to display immediately

            try {
                MapsInitializer.initialize(context);
            } catch (Exception e) {
                e.printStackTrace();
            }
            int errorCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(context);
            if (ConnectionResult.SUCCESS != errorCode) {
                GooglePlayServicesUtil.getErrorDialog(errorCode, (Activity) context, 0)
                        .show();
            } else {
                mapView.getMapAsync(this);
            }

            //MapView support next method,it can be used in fragment life time.
            /*mapView.onCreate(savedInstanceState);
            mapView.onSaveInstanceState(savedInstanceState);
            mapView.onStart();
            mapView.onResume();
            mapView.onPause();
            mapView.onStop();
            mapView.onDestroy();*/
        }
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        map = googleMap;
        map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
        map.setTrafficEnabled(true);
        if (mContext != null) {
            if (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(mContext,
                    android.Manifest.permission.ACCESS_FINE_LOCATION)) {
                map.setMyLocationEnabled(true);
            }
        }
        map.setIndoorEnabled(true);

        if (mLocation != null) {
            LatLng me = new LatLng(mLocation.getLatitude(), mLocation.getLongitude());
            map.addMarker(new MarkerOptions()
                    .position(me)
                    .title("Hello,Marker on my position."));
            map.moveCamera(CameraUpdateFactory.newLatLng(me));
            map.moveCamera(CameraUpdateFactory.zoomTo(16));
        }

    }

    public GoogleMap getMap() {
        return map;
    }

    public void setMap(GoogleMap map) {
        this.map = map;
    }

    public Location getLocation() {
        return mLocation;
    }

    public void setLocation(Location mLocation) {
        this.mLocation = mLocation;
    }

    public SupportMapFragment getMapFragment() {
        return mapFragment;
    }

    public void setMapFragment(SupportMapFragment mapFragment) {
        this.mapFragment = mapFragment;
    }


    private double getMaxLatitude(LatLng[] latLngs) {
        double max = latLngs[0].latitude;
        for (LatLng latlng : latLngs) {
            if (max < latlng.latitude) {
                max = latlng.latitude;
            }
        }
        return max;
    }

    private double getMinLatitude(LatLng[] latLngs) {
        double min = latLngs[0].latitude;
        for (LatLng latlng : latLngs) {
            if (min > latlng.latitude) {
                min = latlng.latitude;
            }
        }
        return min;
    }

    private double getMaxLongitude(LatLng[] latLngs) {
        double max = latLngs[0].longitude;
        for (LatLng latlng : latLngs) {
            if (max < latlng.longitude) {
                max = latlng.longitude;
            }
        }
        return max;
    }

    private double getMinLongitude(LatLng[] latLngs) {
        double min = latLngs[0].longitude;
        for (LatLng latlng : latLngs) {
            if (min > latlng.longitude) {
                min = latlng.longitude;
            }
        }
        return min;
    }

    private LatLng getSouthWestLatLng(LatLng[] latLngs) {
        return new LatLng(getMinLatitude(latLngs), getMinLongitude(latLngs));
    }

    private LatLng getNorthEastLatLng(LatLng[] latLngs) {
        return new LatLng(getMaxLatitude(latLngs), getMaxLongitude(latLngs));
    }

    /**
     * realise to move the marker smoothly.
     *
     * @param marker,   the marker to move
     * @param toLatLng, the LatLng, move to destination position
     */
    private void moveMarkerSmooth(final Marker marker, LatLng toLatLng) {
        if (marker != null) {
            final List<LatLng> roads = new ArrayList<>();
            LatLng fromLatLng = marker.getPosition();    //current position

            LatLng latLng_second = new LatLng((fromLatLng.latitude + toLatLng.latitude) / 2,
                    (fromLatLng.longitude + toLatLng.longitude) / 2);
            LatLng latLng_first = new LatLng((fromLatLng.latitude + latLng_second.latitude) / 2,
                    (fromLatLng.longitude + latLng_second.longitude) / 2);
            LatLng latLng_third = new LatLng((latLng_second.latitude + toLatLng.latitude) / 2,
                    (latLng_second.longitude + toLatLng.longitude) / 2);

            roads.add(latLng_first);
            roads.add(latLng_second);
            roads.add(latLng_third);
            roads.add(toLatLng);
            Thread move = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        for (int i = 0; i < roads.size(); i++) {
                            marker.setPosition(roads.get(i));
                            Thread.sleep(200);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
            move.start();
        }
    }

    public void onResume() {
        if (mapFragment != null) {
            mapFragment.onResume();
        }
    }

    public void onPause() {
        if (mapFragment != null) {
            mapFragment.onPause();
        }
    }

    public void onStop() {
        if (mapFragment != null) {
            mapFragment.onStop();
        }
    }

    /**
     * 这个方法谨慎使用,在activity的onDestroy()会有问题
     */
    public void onDestroy() {
        if (mapFragment != null) {
            mapFragment.onDestroy();
        }
    }

    public void clearMap() {
        if (map != null) {
            map.clear();
        }
    }

    public void setMarkerOnPosition(LatLng latLng) {
        //avoid adding the duplicate marker on map
        if (map != null) {
            if (marker != null) {
                //marker.remove();   //do not use
                marker.setPosition(latLng);
                //moveMarkerSmooth(marker, latLng);
            } else {
                marker = map.addMarker(new MarkerOptions().position(latLng));
                //marker = map.addMarker(new MarkerOptions().position(latLng).icon()); //set marker icon
            }
            Log.d(TAG, "set marker on map");
        }
    }

    public Polyline showRouteOnMap(LatLng[] latLngs) {
        PolylineOptions lineOptions = new PolylineOptions();
        lineOptions.add(latLngs);
        lineOptions.color(Color.BLUE);
        lineOptions.geodesic(true);

        LatLngBounds bounds = new LatLngBounds.Builder()
                .include(getSouthWestLatLng(latLngs))
                .include(getNorthEastLatLng(latLngs))
                .build();

        if (map != null) {
            clearMap();
            Log.d(TAG, "show route on map");
            Polyline line = map.addPolyline(lineOptions);
            map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0));
            return line;
        }
        return null;
    }

}