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

Android API≤24 Cronet提供者禁用崩溃未解决及位置获取咨询

问题1:API 24及以下版本Cronet崩溃解决

崩溃原因

在API 24及以下的Android系统中,默认Cronet提供者可能未预装或处于禁用状态,直接调用CronetEngine.Builder(context).build()会触发All available Cronet providers are disabled运行时异常。

解决方案

通过异常捕获实现降级策略,当Cronet不可用时回退到Media3默认的DefaultHttpDataSource,避免崩溃。修改你的getHttpDataSourceFactory方法如下:

@Synchronized
fun getHttpDataSourceFactory(context: Context): HttpDataSource.Factory {
    if (!DownloadUtil::httpDataSourceFactory.isInitialized) {
        httpDataSourceFactory = try {
            // 尝试构建CronetEngine
            val cronetEngine = CronetEngine.Builder(context).build()
            CronetDataSource.Factory(cronetEngine, Executors.newSingleThreadExecutor())
        } catch (e: RuntimeException) {
            // Cronet不可用时,回退到默认HttpDataSource
            DefaultHttpDataSource.Factory()
        }
    }
    return httpDataSourceFactory
}

额外优化:可以主动尝试启用默认Cronet提供者,但部分设备可能仍不支持,因此降级方案更可靠:

val cronetEngine = CronetEngine.Builder(context)
    .enableDefaultProviders()
    .build()
问题2:所有位置提供者禁用时获取位置

核心说明

LocationManager.getLastKnownLocation()确实可以在位置提供者禁用时返回系统缓存的最后已知位置,但需满足两个条件:

  1. 设备之前成功获取过位置且缓存未过期;
  2. 应用持有ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION权限(Android 10+后台调用还需ACCESS_BACKGROUND_LOCATION)。

如果无缓存位置数据,该方法会返回null,此时无法主动获取新位置,必须引导用户前往系统设置启用位置服务。

实现代码

import android.Manifest
import android.content.Context
import android.location.Location
import android.location.LocationManager
import androidx.core.content.ContextCompat

fun getLastKnownLocation(context: Context): Location? {
    val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
    
    // 检查权限
    val hasFinePerm = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
    val hasCoarsePerm = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED
    if (!hasFinePerm && !hasCoarsePerm) {
        return null
    }
    
    // 遍历所有位置提供者,获取最新缓存位置
    val providers = listOf(LocationManager.GPS_PROVIDER, LocationManager.NETWORK_PROVIDER)
    var latestLocation: Location? = null
    
    for (provider in providers) {
        runCatching {
            locationManager.getLastKnownLocation(provider)
        }.onSuccess { location ->
            location?.let {
                if (latestLocation == null || it.time > latestLocation!!.time) {
                    latestLocation = it
                }
            }
        }
    }
    
    return latestLocation
}

后续处理

如果getLastKnownLocation()返回null,可通过弹窗提示用户:

当前位置服务已禁用,无法获取位置,请前往设置启用位置服务。

内容的提问来源于stack exchange,提问作者Sanjeet Kushwaha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 04:31:03