首页 > IT职业 > IT生活 > 高德地图和google地图适配
今天介绍的是大型app必备模块-地图模块。
当今世界最大的地图sdk应该是google地图,但是由于国内墙掉了google play service,国内是无法使用google地图的,然而国内比较热门的地图sdk是高德地图和百度地图。(如果你是IOS,还有自带的地图)
近来项目中需要世界地图,所以特此做了一个高德地图和google地图兼容的模块了。
1.google地图,接入相对比较简单,当然因为Android本身就是google亲儿子的原因。
需要引入google service的sdk,以及google map的sdk
https://developers.google.com/places/android-api/start,获取账号需要gmail邮箱作为管理
2.高德地图接入相对比较复杂一点,可以选择2d,3d,定位,搜索多种模块去接入地图。
然后需要申请账号,随便邮箱手机号就可以了,通过keytools命令提出keystore的sha1值,包名和
sha1值相互绑定的,每次请求都会验证。
然后配置AndroidManifest中的meta-data。

1.高德地图是通过sdk提供的com.amap.api.maps2d.MapView自定义地图View来实现的。
google地图是通过sdk提供一个Fragment空间来实现地图获取
mapFragment = childFragmentManager.findFragmentById(R.id.google_map) as SupportMapFragment
2.地图预览

Google地图和高德地图接口相关的名字都是差不多的,比较常用的接口
moveCamera 视窗转移 缩放级别分为1~17级,数值越大地图越精准
addMarker 添加地图标签
google地图是使用getMapAysnc,会有onMapReady的接口回调
mapFragment?.getMapAsync(this) /**
* 地图就绪
*/
override fun onMapReady(googleMap: GoogleMap?) {
googleMap ?: return
with(googleMap) {
val latLng = LatLng(latitude, longitude) //视觉转移
moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 16f)) //添加坐标
addMarker(MarkerOptions().position(latLng))
}
}
高德地图使用setOnMapLoadedListener方法来设置回调
aMap?.setOnMapLoadedListener { //视觉移动
aMap?.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(latitude, longitude), 100f)) //添加坐标
aMap?.addMarker(MarkerOptions().anchor(0.5f, 0.5f)
.icon(BitmapDescriptorFactory
.fromBitmap(BitmapFactory.decodeResource(
resources, R.drawable.common_drag_location)))
.position(LatLng(latitude, longitude)))
}
如果不想地图的坐标和视觉点显示居中怎么办?
需要将布局中margin上着手,如果想要往上移,就需要将marginTop设置为负值,这样地图中心点就会上移动,并且视觉点也会和中心点一样上移。

1.高德提供了AMapLocationListener作为专为提供高德坐标的监听
private fun setUpMap() {
myLocationStyle = MyLocationStyle()
myLocationStyle?.strokeColor(Color.argb(0, 0, 0, 0))// 设置圆形的边框颜色
myLocationStyle?.radiusFillColor(Color.argb(0, 0, 0, 0))// 设置圆形的填充颜色
myLocationStyle?.myLocationIcon(BitmapDescriptorFactory.fromResource(R.drawable.common_self_location)) //显示自身定位坐标
aMap?.setMyLocationStyle(myLocationStyle)
aMap?.isMyLocationEnabled = true// 设置为true表示显示定位层并可触发定位,false表示隐藏定位层并不可触发定位,默认是false
val uriSettings = aMap?.uiSettings
uriSettings?.isZoomControlsEnabled = false //关掉缩放键
} private fun initLoc() { //初始化定位
mLocationClient = AMapLocationClient(context!!.applicationContext) //设置定位回调监听
mLocationClient?.setLocationListener(this) //初始化定位参数
mLocationOption = AMapLocationClientOption() //设置定位模式为高精度模式,Battery_Saving为低功耗模式,Device_Sensors是仅设备模式
mLocationOption?.locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy //设置是否返回地址信息(默认返回地址信息)
mLocationOption?.isNeedAddress = true
//设置是否只定位一次,默认为false
mLocationOption?.isOnceLocation = false
//设置是否强制刷新WIFI,默认为强制刷新
mLocationOption?.isWifiActiveScan = false
//设置是否允许模拟位置,默认为false,不允许模拟位置
mLocationOption?.isMockEnable = false
//设置定位间隔,单位毫秒,默认为3000ms
mLocationOption?.interval = (3000) //给定位客户端对象设置定位参数
mLocationClient?.setLocationOption(mLocationOption) //启动定位
mLocationClient?.startLocation()
} override fun onLocationChanged(amapLocation: AMapLocation?) { //监听实时定位
}
google的定位是使用Android原生的Location定位
locationManager = context!!.getSystemService(Context.LOCATION_SERVICE) as LocationManager
locationManager?.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 10f, this)
locationManager?.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 3000, 10f, this)
/**
*地图就绪
*/
override fun onMapReady(googleMap: GoogleMap?) {
googleMap ?: return
this.googleMap = googleMap with(googleMap.uiSettings) {
isZoomGesturesEnabled = true
isMyLocationButtonEnabled = true
isScrollGesturesEnabled = true
} try {
googleMap.isMyLocationEnabled = true
} catch (e: SecurityException) {
ALog.e(TAG, e)
}
} /**
* 定位更新
*/
override fun onLocationChanged(location: Location?) {
}

1.google 搜索有两种方式,一种是通过webapi来搜索出附近相关的地点(这里使用了RxVolley的框架),这个的好处关联结果比较多。
这里不用Uri.Builder的拼接方式是因为其指定了Utf-8的格式转换将会出现“,”强转为“%”号
val googlePlaceUrl = "https://maps.googleapis.com/maps/api/place/nearbysearch/json" fun getGoogleNearByPlaces(latitude: Double, longitude: Double, radius: Int): Observable{ val builder = StringBuilder(googlePlaceUrl) builder.append("?location=").append(latitude.toString()).append(",").append(longitude.toString()) builder.append("&radius=").append(radius.toString()) builder.append("&key=").append(googlePlaceKey) return RxVolley.get (builder.toString(), null, object : TypeToken () {}.type) }
第二种是文字关联搜索(
这边是使用了需要高级定义搜索,所以使用了Adapter的形式。
override fun doSearch(key: String, city: String?) {
Observable.create(ObservableOnSubscribe> {
it.onNext(getAutocomplete(key)!!) //需要在次线程
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
searchAdpater?.clearData() for (item in it) {
val placeResult = mGeoDataClient!!.getPlaceById(item.placeId)
placeResult.addOnCompleteListener(mUpdatePlaceDetailsCallback) //异步访问单个placeId的详细信息
}
}, {
ALog.e(TAG, it)
})
} /**
* 异步访问单个placeId的详细信息
*/
val mUpdatePlaceDetailsCallback = object : OnCompleteListener { override fun onComplete(task: Task) { try {
val place = task.result.get(0)
searchAdpater?.addData(LocationItem(false, place.latLng.latitude, place.latLng.longitude, place.name.toString(), place.address.toString()))
ALog.i(TAG, "Place details received: " + place.name)
task.result.release()
} catch (e: RuntimeRemoteException) {
ALog.e(TAG, e)
}
}
}private fun getAutocomplete(constraint: CharSequence): ArrayList? {
ALog.d(TAG, "Starting autocomplete query for: " + constraint) // Submit the query to the autocomplete API and retrieve a PendingResult that will
// contain the results when the query completes.
val results = mGeoDataClient?.getAutocompletePredictions(constraint.toString(), null, null) // This method should have been called off the main UI thread. Block and wait for at most
// 60s for a result from the API.
//收集文字关联预测结果
try {
Tasks.await(results!!, 2, TimeUnit.SECONDS)
} catch (e: ExecutionException) {
e.printStackTrace()
} catch (e: InterruptedException) {
e.printStackTrace()
} catch (e: TimeoutException) {
e.printStackTrace()
} try {
val autocompletePredictions = results!!.result
ALog.d(TAG, "Query completed. Received " + autocompletePredictions.count
+ " predictions.") // Freeze the results immutable representation that can be stored safely.
return DataBufferUtils.freezeAndClose(autocompletePredictions)
} catch (e: RuntimeExecutionException) { // If the query did not complete successfully return null
Toast.makeText(context, "Error contacting API: " + e.toString(),
Toast.LENGTH_SHORT).show()
ALog.e(TAG, "Error getting autocomplete prediction API call", e) return null
}
}
2.高德地图中的PoiSearch是支持通过关键字搜索和经纬度地址附近搜索。
/**
* 经纬度搜索
*/
fun doSearchQuery(city: String, latitude: Double, longtitude: Double) {
query = PoiSearch.Query("", "", city) // 第一个参数表示搜索字符串,第二个参数表示poi搜索类型,第三个参数表示poi搜索区域(空字符串代表全国)
query?.pageSize = 20 // 设置每页最多返回多少条poiitem
query?.pageNum = 1 // 设置查第一页
val poiSearch = PoiSearch(context, query)
poiSearch.setOnPoiSearchListener(onPoiSearchListener) // 设置搜索区域为以lp点为圆心,其周围5000米范围
poiSearch.bound = PoiSearch.SearchBound(LatLonPoint(latitude, longtitude), 1000, true)
poiSearch.searchPOIAsyn() // 异步搜索
} /**
* 关键字搜索
*/
fun doSearchQuery(keyWord: String, city: String?) { if (city != null)
query = PoiSearch.Query(keyWord, "", city) else
query = PoiSearch.Query(keyWord, "", "")
query?.pageSize = 20 // 设置每页最多返回多少条poiitem
query?.pageNum = 1 // 设置查第一页
val poiSearch = PoiSearch(context!!, query)
poiSearch.setOnPoiSearchListener(onSearchListener)
poiSearch.searchPOIAsyn() // 异步搜索
}
当然也支持异步返回
/**
* 搜索结果
*/
val onSearchListener = object : PoiSearch.OnPoiSearchListener { override fun onPoiSearched(result: PoiResult?, rCode: Int) { if (rCode == 1000) { if (result?.query!! == query) { //返回结果列表
result.pois
}
}
} override fun onPoiItemSearched(p0: PoiItem?, p1: Int) { //返回再搜索
}
}

1.高德地图和google地图都需要使用web api来获取缩略图
var builder: StringBuilder? = null
if (type == GDMAP) {
builder = StringBuilder(gdImgUrl)
builder.append("?location=").append(longitude).append(",").append(latitude)
builder.append("&zoom=").append(zoom)
builder.append("&size=").append(dpToPx(context, width)).append("*").append(dpToPx(context, height))
builder.append("&markers=").append("mid").append(",").append(",A:").append(longitude).append(",").append(latitude)
builder.append("&key=").append(gdMapKey)
} else if (type == GOOGLEMAP) {
builder = StringBuilder(googleImgeUrl)
builder.append("?center=").append(latitude).append(",").append(longitude)
builder.append("&zoom=").append(zoom)
builder.append("&size=").append(dpToPx(context, width)).append("x").append(dpToPx(context, height))
builder.append("&markers=").append(latitude).append(",").append(longitude)
builder.append("&key=").append(googlePlaceKey)
} return builder.toString()
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/1052/viewspace-2806086/ ,如需转载,请注明出处,否则将追究法律责任。