Android 集成google map,Markers ,定位,聚合

集成谷歌地图

前期准备

1.注册谷歌账号,然后再开发者平台登录

开发者平台传送门(需*)
谷歌地图的文档

2.进入控制台,新建项目
Android 集成google map,Markers ,定位,聚合Android 集成google map,Markers ,定位,聚合
3.此时成功创建项目,接下来是添加API,因为谷歌将谷歌地图的功能都拆分成对应的API了,所以需要自己的添加
Android 集成google map,Markers ,定位,聚合
4.点击要使用API,然后启动即可,稍等一会,就会跳转到API界面,查看已添加API列表中是否已经成功开启
Android 集成google map,Markers ,定位,聚合
**PS:谷歌部分API是按需收费的,具体收费金额请自行查看文档
5.最后,查看你在控制台的项目的**,没有的话需要创建,(我已经创建好了)
Android 集成google map,Markers ,定位,聚合
Android 集成google map,Markers ,定位,聚合
**6.创建**成功后,需要对**添加包名和sha-1证书指纹,点击**右边的笔进入修改界面,不知道如何获取sha-1的话,**可以参考此链接
Android 集成google map,Markers ,定位,聚合
最后保存,至此,控制台方面搞定。接下来是代码环节。

添加依赖

implementation 'com.google.android.gms:play-services-maps:16.1.0'
implementation 'com.google.maps.android:android-maps-utils:0.5+'

Android studio 安装google play services
Android 集成google map,Markers ,定位,聚合

打开Android Studio,新建项目,在value\string文件下添加你的**

  <string name="google_map_key">您的api**</string>

打开manifests清单文件,添加标签

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

接着在layout布局中添加fragment控件

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    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.goolgle.MainActivity" />

然后在Activity中,让Activity实现OnMapReadyCallback接口,并重写onMapReady方法,完整代码如下

public class MainActivity extends FragmentActivity
        implements OnMapReadyCallback {
    private GoogleMap mMap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        LatLng sydney = new LatLng(-33.852, 151.211);
        googleMap.addMarker(new MarkerOptions().position(sydney)
                .title("hello world"));
        googleMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
    }

运行,显示以下界面则正常,若显示空白,可能你v*n没有打开。
Android 集成google map,Markers ,定位,聚合

下面介绍一种比较快速的创建项目方法
1.在创建项目的时候选择google maps Activity,然后finish
Android 集成google map,Markers ,定位,聚合
创建好的项目会自动帮你写好代码和布局,但是你直接运行的话,界面是显示空白的,因为你还没有获取到api**,打开google_maps_api.xml。
Android 集成google map,Markers ,定位,聚合
复制以上链接。打开按照步骤获取api**,然后复制到

 <string name="google_maps_key" templateMergeStrategy="preserve" translatable="false">你的**</string>

创建 Markers

在onMapReady()方法中写下以下代码,便可创建标点

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

        // Add a marker in Sydney and move the camera
        LatLng sydney = new LatLng(-34, 151);
        mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
        mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
		//创建markers
        googleMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
        googleMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
        googleMap.addMarker(new MarkerOptions().position(new LatLng(23.12, 113.26)).title("广州"));
        googleMap.addMarker(new MarkerOptions().position(new LatLng(23.12, 113.26)).title("越秀"));
        googleMap.addMarker(new MarkerOptions().position(new LatLng(23.12, 113.24)).title("荔湾"));
        googleMap.addMarker(new MarkerOptions().position(new LatLng(23.08, 113.31)).title("海珠"));
        googleMap.addMarker(new MarkerOptions().position(new LatLng(23.12, 113.36)).title("天河"));
        googleMap.addMarker(new MarkerOptions().position(new LatLng(23.15, 113.27)).title("白云"));
        googleMap.addMarker(new MarkerOptions().position(new LatLng(23.18, 113.48)).title("黄埔"));
        googleMap.addMarker(new MarkerOptions().position(new LatLng(23.56, 116.41)).title("揭东"));
        googleMap.addMarker(new MarkerOptions().position(new LatLng(23.03, 116.29)).title("惠来"));
        googleMap.addMarker(new MarkerOptions().position(new LatLng(23.43, 115.84)).title("揭西"));
        googleMap.addMarker(new MarkerOptions().position(new LatLng(22.91, 112.04)).title("云浮"));
    }
}

运行效果
Android 集成google map,Markers ,定位,聚合

定位

添加依赖:

   implementation 'com.google.android.gms:play-services-maps:16.1.0'   
    implementation 'com.google.maps.android:android-maps-utils:0.5+'

想要实现定位功能,便需要实现 GoogleMap.OnMyLocationButtonClickListener,
GoogleMap.OnMyLocationClickListener,ActivityCompat.OnRequestPermissionsResultCallback三个接口,代码如下:

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GoogleMap.OnMyLocationButtonClickListener,
        GoogleMap.OnMyLocationClickListener, ActivityCompat.OnRequestPermissionsResultCallback{

    private GoogleMap mMap;
    private static final int LOCATION_PERMISSION_REQUEST_CODE = 1;
    private boolean mPermissionDenied = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }


    /**
     * Manipulates the map once available.
     * This callback is triggered when the map is ready to be used.
     * This is where we can add markers or lines, add listeners or move the camera. In this case,
     * we just add a marker near Sydney, Australia.
     * If Google Play services is not installed on the device, the user will be prompted to install
     * it inside the SupportMapFragment. This method will only be triggered once the user has
     * installed Google Play services and returned to the app.
     */
    @Override
    public void onMapReady(GoogleMap googleMap) {
        //定位
        mMap = googleMap;
        mMap.setOnMyLocationButtonClickListener(this);
        mMap.setOnMyLocationClickListener(this);
        enableMyLocation();
    }
    private void enableMyLocation() {
        if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            // Permission to access the location is missing.
            PermissionUtils.requestPermission(this, LOCATION_PERMISSION_REQUEST_CODE,
                    android.Manifest.permission.ACCESS_COARSE_LOCATION, true);
        } else if (mMap != null) {
            // 设置地图上显示手机的位置,和显示控制按钮
            mMap.setMyLocationEnabled(true);
            //设置室内地图是否开启
            mMap.setIndoorEnabled(true);
            //设置地图的类型
            mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
        }
    }
    //定位图标点击事件
    @Override
    public boolean onMyLocationButtonClick() {
        return false;
    }

    @Override
    public void onMyLocationClick(@NonNull Location location) {

    }
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        if (requestCode != LOCATION_PERMISSION_REQUEST_CODE) {
            return;
        }
        if (PermissionUtils.isPermissionGranted(permissions, grantResults,
                android.Manifest.permission.ACCESS_COARSE_LOCATION)) {
            // Enable the my location layer if the permission has been granted.
            enableMyLocation();
        } else {
            // Display the missing permission error dialog when the fragments resume.
            mPermissionDenied = true;
        }
    }
    @Override
    protected void onResumeFragments() {
        super.onResumeFragments();
        if (mPermissionDenied) {
            // Permission was not granted, display error dialog.
            showMissingPermissionError();
            mPermissionDenied = false;
        }
    }
    private void showMissingPermissionError() {
        PermissionUtils.PermissionDeniedDialog
                .newInstance(true).show(getSupportFragmentManager(), "dialog");
    }
}

PermissionUtils类代码

public abstract class PermissionUtils {

    /**
     * Requests the fine location permission. If a rationale with an additional explanation should
     * be shown to the user, displays a dialog that triggers the request.
     */
    public static void requestPermission(MapsActivity activity, int requestId,
                                         String permission, boolean finishActivity) {
        if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {
            // Display a dialog with rationale.
            PermissionUtils.RationaleDialog.newInstance(requestId, finishActivity)
                    .show(activity.getSupportFragmentManager(), "dialog");
        } else {
            // Location permission has not been granted yet, request it.
            ActivityCompat.requestPermissions(activity, new String[]{permission}, requestId);

        }
    }

    /**
     * Checks if the result contains a {@link PackageManager#PERMISSION_GRANTED} result for a
     * permission from a runtime permissions request.
     *
     * @see android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback
     */
    public static boolean isPermissionGranted(String[] grantPermissions, int[] grantResults,
                                              String permission) {
        for (int i = 0; i < grantPermissions.length; i++) {
            if (permission.equals(grantPermissions[i])) {
                return grantResults[i] == PackageManager.PERMISSION_GRANTED;
            }
        }
        return false;
    }

    /**
     * A dialog that displays a permission denied message.
     */
    public static class PermissionDeniedDialog extends DialogFragment {

        private static final String ARGUMENT_FINISH_ACTIVITY = "finish";

        private boolean mFinishActivity = false;

        /**
         * Creates a new instance of this dialog and optionally finishes the calling Activity
         * when the 'Ok' button is clicked.
         */
        public static PermissionDeniedDialog newInstance(boolean finishActivity) {
            Bundle arguments = new Bundle();
            arguments.putBoolean(ARGUMENT_FINISH_ACTIVITY, finishActivity);

            PermissionDeniedDialog dialog = new PermissionDeniedDialog();
            dialog.setArguments(arguments);
            return dialog;
        }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            mFinishActivity = getArguments().getBoolean(ARGUMENT_FINISH_ACTIVITY);

            return new AlertDialog.Builder(getActivity())
                    .setMessage(R.string.location_permission_denied)
                    .setPositiveButton(android.R.string.ok, null)
                    .create();
        }

        @Override
        public void onDismiss(DialogInterface dialog) {
            super.onDismiss(dialog);
            if (mFinishActivity) {
                Toast.makeText(getActivity(), R.string.permission_required_toast,
                        Toast.LENGTH_SHORT).show();
                getActivity().finish();
            }
        }
    }

    /**
     * A dialog that explains the use of the location permission and requests the necessary
     * permission.
     * <p>
     * The activity should implement
     * {@link android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback}
     * to handle permit or denial of this permission request.
     */
    public static class RationaleDialog extends DialogFragment {

        private static final String ARGUMENT_PERMISSION_REQUEST_CODE = "requestCode";

        private static final String ARGUMENT_FINISH_ACTIVITY = "finish";

        private boolean mFinishActivity = false;

        /**
         * Creates a new instance of a dialog displaying the rationale for the use of the location
         * permission.
         * <p>
         * The permission is requested after clicking 'ok'.
         *
         * @param requestCode    Id of the request that is used to request the permission. It is
         *                       returned to the
         *                       {@link android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback}.
         * @param finishActivity Whether the calling Activity should be finished if the dialog is
         *                       cancelled.
         */
        public static RationaleDialog newInstance(int requestCode, boolean finishActivity) {
            Bundle arguments = new Bundle();
            arguments.putInt(ARGUMENT_PERMISSION_REQUEST_CODE, requestCode);
            arguments.putBoolean(ARGUMENT_FINISH_ACTIVITY, finishActivity);
            RationaleDialog dialog = new RationaleDialog();
            dialog.setArguments(arguments);
            return dialog;
        }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            Bundle arguments = getArguments();
            final int requestCode = arguments.getInt(ARGUMENT_PERMISSION_REQUEST_CODE);
            mFinishActivity = arguments.getBoolean(ARGUMENT_FINISH_ACTIVITY);

            return new AlertDialog.Builder(getActivity())
                    .setMessage(R.string.permission_rationale_location)
                    .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            // After click on Ok, request the permission.
                            ActivityCompat.requestPermissions(getActivity(),
                                    new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION,
                                            android.Manifest.permission.ACCESS_COARSE_LOCATION},
                                    requestCode);
                            // Do not finish the Activity while requesting permission.
                            mFinishActivity = false;
                        }
                    })
                    .setNegativeButton(android.R.string.cancel, null)
                    .create();
        }

        @Override
        public void onDismiss(DialogInterface dialog) {
            super.onDismiss(dialog);
            if (mFinishActivity) {
                Toast.makeText(getActivity(),
                        R.string.permission_required_toast,
                        Toast.LENGTH_SHORT)
                        .show();
                getActivity().finish();
            }
        }
    }
}

运行后,如果出现以下提示

Android 集成google map,Markers ,定位,聚合
那是因为定位权限没有开启,在设置里面打开即可,点击定位按钮,即可定位,但是因为在国内使用定位会有偏差。Android 集成google map,Markers ,定位,聚合

聚合

代码如下

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback{

    private ClusterManager<MyItem> mClusterManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
    
        setUpClusterer();
        
    }
    //以下是聚合代码
    private void setUpClusterer() {
        // Position the map.
        getMap().moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(51.503186, -0.126446), 5.5f));

        // Initialize the manager with the context and the map.
        // (Activity extends context, so we can pass 'this' in the constructor.)
        mClusterManager = new ClusterManager<MyItem>(this, getMap());
        mClusterManager.setAnimation(true);

        // Point the map's listeners at the listeners implemented by the cluster
        // manager.
        getMap().setOnCameraIdleListener(mClusterManager);
        getMap().setOnMarkerClickListener(mClusterManager);

        // Add cluster items (markers) to the cluster manager.
        addItems();
    }

    private void addItems() {

        // Set some lat/lng coordinates to start with.
        double lat = 51.5145160;
        double lng = -0.1270060;

        // 创建标点
        for (int i = 0; i < 50; i++) {
            double offset = i / 60d;
            lat = lat + offset;
            lng = lng + offset;
            String title = "This is the title"+i;
            String snippet = "and this is the snippet"+i;
            MyItem offsetItem = new MyItem(lat, lng,title,snippet);
            mClusterManager.addItem(offsetItem);
        }
    }
    protected GoogleMap getMap() {
        return mMap;
    }
}

MyItem代码

public class MyItem implements ClusterItem {
    private final LatLng mPosition;
    private String mTitle;
    private String mSnippet;

    public MyItem(double lat, double lng) {
        mPosition = new LatLng(lat, lng);
    }

    public MyItem(double lat, double lng, String title, String snippet) {
        mPosition = new LatLng(lat, lng);
        mTitle = title;
        mSnippet = snippet;
    }

    @Override
    public LatLng getPosition() {
        return mPosition;
    }

    @Override
    public String getTitle() {
        return mTitle;
    }

    @Override
    public String getSnippet() {
        return mSnippet;
    }
}

运行
Android 集成google map,Markers ,定位,聚合