Android Osmdroid + 天地图 (一)
Osmdroid + 天地图
- 前言
- 正文
- 一、配置build.gradle
- 二、配置AndroidManifest.xml
- 三、获取天地图的API Key
- ① 获取开发版SHA1
- ② 获取发布版SHA1
- 四、请求权限
- 五、显示地图
- 六、源码
前言
Osmdroid是一款完全开源的地图基本操作SDK,我们可以通过这个SDK去加一些地图API,比如腾讯、百度、高德、Google等等。天地图API也是一个地图服务提供商,不过之前还是提供Android的地图SDK的,现在就只提供了API服务了,那么为什么我们会想到这个天地图API呢?因为贫穷,贫穷使我们相遇,如果你是个人项目不上架的那种我推荐你使用高德、百度、腾讯3家,但如果你要上架的话就涉及到一个可能会被宰的问题了,这3家商业授权都是5万一年,那不是开玩笑的,如果你的应用不是主导地图的话,完全犯不上去使用,下面我们进入正文去使用天地图API,效果图如下所示:
正文
点击天地图API进入,之后完成注册登录及个人或企业开发者的认证工作,然后就到了喜闻乐见的创建Android项目的环节了。
一、配置build.gradle
这里我们就使用Empty Views Activity的模板,点击Next。
修改一下项目名和包名,这个包名在下面的获取API Key要用到的,注意这里的构建配置语言也是Kotlin的,如果你不习惯,请改成Groovy,然后运行能看到Hello World!
即可。
因为我们需要使用Osmdroid
SDK库,所以我们现在app
模块下的build.gradle.kts
文件中导入如下代码:
implementation("org.osmdroid:osmdroid-android:6.1.20")
这个库在mavenCentral()
下,然后再配置viewBinding,代码如下所示:
buildFeatures {
viewBinding = true
}
上述代码配置如下图所示:
二、配置AndroidManifest.xml
因为用到地图自然就涉及到定位,还有API的使用就涉及到网络,而网络从Android8.0之后就默认是https请求方式,如果需要http的话则配置一下,针对上述的3个要求,我们首先配置一下权限,在AndroidManifest.xml
中增加如下代码:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
然后在res
下的xml
目录下创建一个network_security_config.xml
文件里面代码如下所示:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
这个文件的配置内容就是允许http访问,我们需要在AndroidManifest.xml
中的application
标签中进行配置,如下所示:
android:networkSecurityConfig="@xml/network_security_config"
上述的配置如下图所示:
三、获取天地图的API Key
相信你已经完成了我前面讲到的工作了,那么进入控制台,点击创建新应用。
可以看到这里我们需要发布版SHA1、开发版SHA1
和包名
,包名我们创建项目的时候就有了。
① 获取开发版SHA1
首先我们来说明一下开发版SHA1
的获取方式,刚才我们运行过了,下面使用快捷键Win+R,输入cmd,进入命令窗口,输入
cd .android
回车,然后输入
keytool -list -v -keystore debug.keystore
回车,会让你输入密码,密码就是android,输入后回车就看到一大串信息,其中就有我们SHA1,注意我们使用的是debug.keystore,所以得到的就是开发版SHA1,这个值在不同的电脑上就不一样,请注意。
复制一下粘贴过去即可。
② 获取发布版SHA1
下面来获取发布版SHA1,这个稍微麻烦一点,我们需要先生成一个APK。
点击Build
➡️Generate Signed App Bundle/ APK...
这里选择APK
,点击Next。
点击Create new...
可以参考我这个方式去设置,这里我的两个密码都是一样的,你可以不一样,前提是你记得住,需要注意是的这个jks文件生成的位置,我是直接生成到项目的目录下了,点击OK
。
勾选上Remeber passwords
,点击Next
。
点击Create
等待生成APK。
当你在AS的右下角看到这个弹窗时,表示生成APK成功了,切换到Project模式查看一下,如下图所示:
下面就是正式获取发布版SHA1的过程了,本来上面这一大串我是不想写的,但是又考虑到是小白的话,就还是写了,点击AS底部的Terminal
,打开后默认就是当前项目的目录,然后我们只要输入
keytool -list -v -keystore .\openMap.jks
keytool -list -v -keystore
后面的是你的jks的文件路径,如果你不是我这么配置的请写自己的实际路径,然后回车,输入密码再回车即可看到发布版SHA1,如下图所示:
下面回到天地图那个网页,此时我们已经填好了所有需要的值。
点击提交,就是提示创建成功,如果提示创建失败的话,你再点一次,有网络延迟的问题。创建成功就得到了我们访问天地图的Key了,如下图所示:
这个Key我们在项目中需要用到的,我们可以在com.llw.openmap
下创建一个Config
类,这里面配置这个Key,代码如下所示:
object Config {
const val MAP_KEY = "f951c7d1b85975379f6ee20bb264abba"
}
四、请求权限
进入MainActivity
,增加代码如下所示:
// 定位权限
private val permissions = arrayOf(
android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.ACCESS_COARSE_LOCATION,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
android.Manifest.permission.READ_EXTERNAL_STORAGE
)
// 权限申请
private val permissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result ->
if (!result.containsValue(false)) initMap() else requestPermission()
}
首先我们定义了定位权限和权限请求返回,使用ActivityResult API的方式,然后我们需要写initMap()
和checkPermission()
函数,代码如下所示:
/**
* 初始化地图
*/
private fun initMap() {
}
/**
* 检查权限
*/
private fun checkPermission() {
permissions.forEach { permission ->
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
// 请求权限
requestPermission()
return
}
}
// 初始化地图
initMap()
}
/**
* 请求权限
*/
private fun requestPermission() {
permissionLauncher.launch(permissions)
}
最后我们在onResume()
生命周期中检查权限,调用checkPermission()
,代码如下所示:
override fun onResume() {
super.onResume()
// 检查权限
checkPermission()
}
目前为止整个页面代码如下图所示:
为什么我要贴图呢,因为是真的有人把代码写错位置,然后问我为什么报错?现在我们运行一下,你会发现弹窗请求权限,同意之后会看到都是格子,因为我们还没有加载地图API的,这里我们就要加载天地图。
五、显示地图
要显示地图就需要用到Osmdroid了,在Config中添加如下代码:
// 默认GeoPoint
val defaultGeoPoint = GeoPoint(39.909, 116.39742)
/**
* 天地图 有标注电子地图
*/
var TDTCIA_W: OnlineTileSourceBase = object : XYTileSource(
"Tian Di Tu CIA",
0, 20, 256, "",
arrayOf(
"http://t0.tianditu.com/DataServer?T=cia_w&tk=$MAP_KEY",
"http://t1.tianditu.com/DataServer?T=cia_w&tk=$MAP_KEY",
"http://t2.tianditu.com/DataServer?T=cia_w&tk=$MAP_KEY",
"http://t3.tianditu.com/DataServer?T=cia_w&tk=$MAP_KEY",
"http://t4.tianditu.com/DataServer?T=cia_w&tk=$MAP_KEY",
"http://t5.tianditu.com/DataServer?T=cia_w&tk=$MAP_KEY",
"http://t6.tianditu.com/DataServer?T=cia_w&tk=$MAP_KEY",
"http://t7.tianditu.com/DataServer?T=cia_w&tk=$MAP_KEY"
)
) {
override fun getTileURLString(pMapTileIndex: Long) =
("$baseUrl&X=${MapTileIndex.getX(pMapTileIndex)}&Y=${MapTileIndex.getY(pMapTileIndex)}&L=${MapTileIndex.getZoom(pMapTileIndex)}")
}
添加了一个默认的经纬度坐标,然后通过Osmdroid去加载天地图的在线瓦片资源,然后回到MainActivity,这里首先我们用上ViewBinding,代码如下所示:
private lateinit var binding: ActivityMainBinding
然后在onCreate中配置代码,如下所示:
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
位置如下图所示:
下面进入initMap()
中去配置地图,代码如下所示:
private fun initMap() {
binding.mapView.apply {
setTileSource(Config.TDTCIA_W) // 设置瓦片地图资源
minZoomLevel = 5.0 // 最小缩放级别
maxZoomLevel = 20.0 // 最大缩放级别
isTilesScaledToDpi = true // 图块是否缩放到 DPI
// 设置默认的地图中心点
controller.apply {
setZoom(12.0)
setCenter(Config.defaultGeoPoint)
}
zoomController.setVisibility(Visibility.NEVER)
setMultiTouchControls(true)
overlayManager.tilesOverlay.isEnabled = true
}
}
下面可以运行一下,我从头开始运行一下:
虽然可能效果不是特别好,但是起码是个地图啊,免费的你还要什么自行车。
六、源码
如果对你有所帮助的话,不妨欢迎Star
和Fork
。
源码地址:OpenMap
APK下载地址:OpenMap1.0.apk