You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

清除应用存储后OSMDroid示例代码无法加载地图瓦片的求助

问题解决思路

核心问题定位

  1. Android 13+存储权限适配失效:WRITE_EXTERNAL_STORAGE权限已废弃,系统不再授予,导致osmdroid无法创建外部缓存目录,触发空指针错误。
  2. SSL握手失败:MAPNIK瓦片服务器的证书链验证不通过,无法下载瓦片。
  3. 缓存目录未正确初始化:清除存储后,默认缓存路径丢失,未自动重建。

分步解决方案

1. 适配Android 13+存储权限(推荐使用应用私有存储)

无需申请外部存储权限,直接配置osmdroid使用应用私有目录存储瓦片缓存,彻底规避权限问题:

private lateinit var map: MapView
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    
    // 初始化osmdroid配置,指定应用私有缓存目录
    val config = Configuration.getInstance()
    val appCacheDir = File(filesDir, "osmdroid_cache")
    config.setOsmdroidBasePath(appCacheDir)
    config.setOsmdroidTileCache(File(appCacheDir, "map_tiles"))
    
    // 加载配置并设置布局
    config.load(this, PreferenceManager.getDefaultSharedPreferences(this))
    setContentView(R.layout.main)

    map = findViewById(R.id.map)
    map.setTileSource(TileSourceFactory.MAPNIK)
}

同时移除Manifest中已废弃的WRITE_EXTERNAL_STORAGE、READ_EXTERNAL_STORAGE权限,以及android:requestLegacyExternalStorage="true"配置。

2. 修复SSL握手失败问题

MAPNIK瓦片服务器使用Let's Encrypt证书,部分设备因根证书缺失导致验证失败,可选择以下方案:

  • 方案一:更换兼容瓦片源
    改用证书验证无问题的瓦片源,例如:
    map.setTileSource(TileSourceFactory.OpenTopo)
    
  • 方案二:临时跳过SSL验证(仅测试用)
    创建信任所有证书的SSL配置注入osmdroid下载器(不推荐生产环境使用):
    // 提前在初始化前配置
    fun createUnsafeSSLContext(): SSLContext {
        val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
            override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {}
            override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {}
            override fun getAcceptedIssuers(): Array<X509Certificate> = emptyArray()
        })
        val sslContext = SSLContext.getInstance("SSL")
        sslContext.init(null, trustAllCerts, SecureRandom())
        return sslContext
    }
    
    // 在onCreate中地图初始化前调用
    val sslContext = createUnsafeSSLContext()
    OkHttpClientFactory.setOkHttpClient(
        OkHttpClient.Builder()
            .sslSocketFactory(sslContext.socketFactory, sslContext.trustManager as X509TrustManager)
            .hostnameVerifier { _, _ -> true }
            .build()
    )
    

3. 确保缓存目录可写

添加代码主动创建并验证缓存目录,避免空指针:

val appCacheDir = File(filesDir, "osmdroid_cache")
if (!appCacheDir.exists()) {
    appCacheDir.mkdirs()
}
val tileCacheDir = File(appCacheDir, "map_tiles")
if (!tileCacheDir.exists()) {
    tileCacheDir.mkdirs()
}

// 验证可写性
if (StorageUtils.isWritable(tileCacheDir)) {
    Log.d("Osmdroid", "缓存目录可写")
} else {
    Log.e("Osmdroid", "缓存目录不可写")
}

内容的提问来源于stack exchange,提问作者Malachi Holden

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 14:49:57