步骤
- 在 Android 项目中添加 WebView
- 创建一个 HTML 文件来加载 Leaflet
- 在
MapActivity
中加载该 HTML 文件
1. 在 Android 项目中添加 WebView
创建你的 activity_map.xml
文件并添加一个 WebView:
<!-- res/layout/activity_map.xml -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
2. 创建一个 HTML 文件来加载 Leaflet
在 assets
文件夹中创建一个 map.html
文件。确保在 app/src/main/assets
路径下创建 assets
文件夹。下面是示例代码:
<!DOCTYPE html>
<html>
<head>
<title>Leaflet Map</title>
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
<link rel="stylesheet" href="leaflet.css" />
<style>
body {
padding: 0;
margin: 0;
}
html, body, #map {
height: 100%;
width: 100vw;
}
</style>
</head>
<body>
<div id="map"></div>
<script src="leaflet.js" ></script>
<script src="leaflet.ChineseTmsProviders.js"></script>
<script>
var map = L.map('map').fitWorld();
<!--天地图-->
L.tileLayer.chinaProvider(
'TianDiTu.Normal.Map',
{
key: '你的密钥',
maxZoom:18,
minZoom:5,
}).addTo(map);
L.tileLayer.chinaProvider(
'TianDiTu.Normal.Annotion',
{
key: '你的密钥',
maxZoom:18,
minZoom:5,
}).addTo(map);
<!--开放街道地图-->
<!-- var map = L.map('map').fitWorld();-->
<!-- L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {-->
<!-- maxZoom: 19,-->
<!-- attribution: '© OpenStreetMap'-->
<!-- }).addTo(map);-->
map.setView([35.8617, 104.1954], 4); // 设置视图到中国的中心点
</script>
</body>
</html>
这里要一起加载两个图层,因为一个是地图,一个是注记(显示地名的),因为我使用的js都是下载下来的,其实你可以使用在线的:
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" />
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
其中Leaflet.ChineseTmsProviders.js可用可不用,但是不用的话一定不要使用这种格式来获取
L.tileLayer('http://{s}.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=你的密钥', {
maxZoom: 18,
attribution: '© Tianditu',
subdomains: ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7', 't8', 't9']
}).addTo(map);
不使用Leaflet.ChineseTmsProviders.js的话,直接删除subdomains,用准确的地址去获取
L.tileLayer('http://t0.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=你的密钥', {
maxZoom: 18,
attribution: '© Tianditu',
}).addTo(map);
不然天地图加载出来会有一连串阶梯状的瓦片加载不出来,
使用Leaflet.ChineseTmsProviders.js的话,对于安卓我的建议是直接下载下来本地使用:GitHub - htoooth/Leaflet.ChineseTmsProviders: Provider for Chinese Tms Service
这里有一步十分关键,如果不改,Android端将无法加载天地图,这是我通过Chrome DevTools调试工具调试出来的,打开下载的Leaflet.ChineseTmsProviders.js,找到天地图的位置,进行如下修改:
TianDiTu: {
Normal: {
// Map: "//t{s}.tianditu.gov.cn/DataServer?T=vec_w&X={x}&Y={y}&L={z}&tk={key}",
Map: "https://t{s}.tianditu.gov.cn/DataServer?T=vec_w&X={x}&Y={y}&L={z}&tk={key}",
// Annotion: "t{s}.tianditu.gov.cn/DataServer?T=cva_w&X={x}&Y={y}&L={z}&tk={key}"
Annotion: "https://t{s}.tianditu.gov.cn/DataServer?T=cva_w&X={x}&Y={y}&L={z}&tk={key}"
},
Satellite: {
Map: "//t{s}.tianditu.gov.cn/DataServer?T=img_w&X={x}&Y={y}&L={z}&tk={key}",
Annotion: "//t{s}.tianditu.gov.cn/DataServer?T=cia_w&X={x}&Y={y}&L={z}&tk={key}"
},
Terrain: {
Map: "//t{s}.tianditu.gov.cn/DataServer?T=ter_w&X={x}&Y={y}&L={z}&tk={key}",
Annotion: "//t{s}.tianditu.gov.cn/DataServer?T=cta_w&X={x}&Y={y}&L={z}&tk={key}"
},
Subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
key: "174705aebfe31b79b3587279e211cb9a"
},
就是在原来的url构建上加上https:,如果不加的话Android端的请求是这个样子:file://t5.tianditu.gov.cn/DataServer?T=cva_w&X=101&Y=48&L=7&tk=********。当然你可以去改其它位置,不一定要像我这样改。
3. 在 MapActivity
中加载该 HTML 文件
修改 MapActivity
以加载 HTML 文件并通过 JavaScript 与 WebView 进行交互。
import android.annotation.SuppressLint
import android.os.Bundle
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
class MapActivity : AppCompatActivity() {
private lateinit var webView: WebView
@SuppressLint("SetJavaScriptEnabled")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_map)
webView = findViewById(R.id.mapView)
webView.webViewClient = WebViewClient()
val webSettings: WebSettings = webView.settings
webSettings.javaScriptEnabled = true
webSettings.domStorageEnabled = true
webSettings.allowFileAccess = true
webSettings.allowContentAccess = true
webSettings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW // 允许加载混合内容
webView.loadUrl("file:///android_asset/map.html")
}
这是kotlin代码,对于Android studio可以直接复制粘贴,它可以帮你转换成Java
这些文件的位置是:
app/
└── src/
└── main/
└── assets/
├── leaflet.js
├── Leaflet.ChineseTmsProviders.js
├── leaflet.css
└── map.html
└── java/
└── res/
└── layout/
└── activity_map.xml
最后在AndroidManifest.xml里配置权限和引入MapActivity就可以了
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<activity
android:name=".MapActivity"
android:exported="true"
android:label="Map Activity" />
效果图: