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()确实可以在位置提供者禁用时返回系统缓存的最后已知位置,但需满足两个条件:
- 设备之前成功获取过位置且缓存未过期;
- 应用持有
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
相关产品推荐
相关产品推荐

