引言
项目需求需要在谷歌地图:
地图展示,设备点聚合,设备站点,绘制点和区域等功能。
我只针对我涉及到的技术做一下总结,希望能帮到开始接触谷歌地图的伙伴们。
集成步骤
1、在项目的modle的build.gradle中添加依赖如下:
implementation 'com.google.android.gms:play-services-maps:12.0.1'
// 地图操作工具类,添加标记等
implementation 'com.google.maps.android:android-maps-utils:0.5+'
2、集成完了后,需要展示地图,这里由于谷歌地图是已经被屏蔽,需要翻墙操作才能展示。
①首先我们要注册一个谷歌账号
②使用谷歌账号登录谷歌地图开发者平台(登录网站:https://cloud.google.com/maps-platform/?hl=zh-CN),点击控制台,如图
点击控制进入控制台进行如下操作,生成谷歌地图的appkey:
点击API秘钥,生成秘钥,在生成的秘钥界面上我们点击秘钥限制,设置成android ,点击确定就生成了我们所需的appkey。
将生成的API密钥复制并粘贴到您的Android应用程序的相应位置,通常在AndroidManifest.xml
中的<application>
标签内,如下所示:
<application>
<!-- 其他配置 -->
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="YOUR_GOOGLE_MAPS_API_KEY"/>
<!-- 其他配置 -->
</application>
替换YOUR_GOOGLE_MAPS_API_KEY
为您从Google Developers Console获得的API密钥。
请注意,您需要为调试和发布版本获取不同的密钥,并为每种版本使用正确的SHA-1证书指纹。
项目开发
地图展示
向应用中添加Google Map组件有两种基本的方式:
1、一种是利用MapFragment(Fragment的子类,内部集成GoogleMap)
2、另一种是用MapView(View的子类,内部集成GoogleMap)。
一、MapFragment
1.地图展示:分为两加载地图:
一种是在activity中动态或者是静态加载我们的谷歌地图的fragment,进行显示。
静态加载
首先说一下在activity中静态加载地图的fragment。核心代码如下:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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.googlemapdemo.MapsMarkerActivity" />
class MapsMarkerActivity : AppCompatActivity() , OnMapReadyCallback {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment?
mapFragment!!.getMapAsync(this)
}
override fun onMapReady(map : GoogleMap?) {
}
}
这样一张谷歌地图就展示出来,显示的原因是通过mapFragment.getMapAsync()方法映射注册回调地图监听(因为谷歌地图被屏蔽了,所以需要翻墙才能看到地图,如果没有翻墙,是空白一片,并且android手机里面必须安装谷歌三件套,否则也不能显示)。
动态加载
布局:
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/my_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.googlemapdemo.MapsMarkerActivity" />
activity 代码:
创建一个MapFragment对象,并利用FragmentTransaction动态添加到指定的容器中:
class MapsMarkerActivity : AppCompatActivity() , OnMapReadyCallback {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment?
// mapFragment!!.getMapAsync(this)
val fragmentManager = supportFragmentManager
val mapFragment = SupportMapFragment.newInstance()
fragmentManager.beginTransaction().replace(R.id.map_container, mapFragment as Fragment ).commit()
mapFragment.getMapAsync(this)
}
override fun onMapReady(map : GoogleMap?) {
}
}
二、MapView
MapView是View的子类,只需要在布局文件中引用com.google.android.gms.maps.MapView定义一个MapView,然后在Activity初始化MapView,与普通的TextView等组件用法类似。
xml:
//layout文件中的定义
<com.google.android.gms.maps.MapView
android:id="@+id/mymap"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
activity :
//Activity中的初始化
myMap = (MapView)findViewById(R.id.mymap);
myMap.getMapAsync(this);//getMapAsync这个与MapFragment相同
需要特别注意的是,MapView中生命周期的方法必须与Activity生命周期的方法同步,即必须在Activity中的生命周期中调用MapView的生命周期函数。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
```````//其他的一些初始化
myMap.onCreate(savedInstanceState);
}
@Override
protected void onResume() {
super.onResume();
myMap.onResume();
}
@Override
protected void onPause() {
super.onPause();
myMap.onPause();
}
@Override
protected void onDestroy() {
super.onDestroy();
myMap.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
myMap.onLowMemory();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
myMap.onSaveInstanceState(outState);
}
onMapReady
onMapReady()是一个回调方法,用于在地图准备就绪后获取初始坐标。
当地图准备就绪时,系统会调用该方法,并传入一个GoogleMap对象作为参数,开发者可以通过该对象进行地图相关的操作。
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// 获取当前位置的经纬度
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// 请求权限
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
} else {
// 获取到位置权限后,获取当前位置经纬度
mMap.setMyLocationEnabled(true);
LatLng latLng = new LatLng(mMap.getMyLocation().getLatitude(), mMap.getMyLocation().getLongitude());
mMap.addMarker(new MarkerOptions().position(latLng).title("当前位置"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
}
}
在onMapReady
回调中,我们首先检查定位权限,如果已经授予,我们就启用地图上的位置指示(通过调用setMyLocationEnabled(true)
),然后可以获取当前的位置(通过调用getMyLocation()
),并在地图上设置一个标记(通过调用addMarker()
)以及移动相机到当前位置(通过调用moveCamera()
)。如果没有定位权限,我们请求权限,并在权限被授予后执行上述操作。
三、组件的初始化
当需要初始化Map的一些状态时,可以在xml属性中设置,也可以在java代码中设置。
1.xml属性初始化
在fragment或者MapView的xml布局中,都可以添加一些属性来初始化Map的状态。
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:cameraBearing="112.5"
map:cameraTargetLat="-33.796923"
map:cameraTargetLng="150.922433"
map:cameraTilt="30"
map:cameraZoom="13"
map:mapType="normal"
map:uiCompass="false"
map:uiRotateGestures="true"
map:uiScrollGestures="false"
map:uiTiltGestures="true"
map:uiZoomControls="false"
map:uiZoomGestures="true"/>
GoogleMapOptions options = new GoogleMapOptions();
options.mapType(GoogleMap.MAP_TYPE_SATELLITE)
.compassEnabled(false)
.rotateGesturesEnabled(false)
.tiltGesturesEnabled(false);
//在实例化一个MapFragment对象时
MapFragment.newInstance(GoogleMapOptions options);
//或者MapView的构造函数中
MapView(Context, GoogleMapOptions)