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

Downloadable Fonts异常求助:非FontCallback方案适配需求(minSdk16)

针对Downloadable Fonts调用ResourcesCompat抛异常的解决方案(minSdk16、禁用v27 FontCallback)

我之前也踩过Downloadable Fonts的类似坑,结合你的限制条件,给你几个针对性的排查和解决方向:

1. 先排查字体XML配置的正确性

这是最容易出错的环节,尤其是无GMS设备也会报错,大概率配置有问题:

  • 检查res/font/下的字体配置XML,确保<font-family>中的属性完全正确:
    • app:fontProviderAuthority:如果用Google Fonts,必须是com.google.android.gms.fonts;自定义provider则要对应你的授权值。
    • app:fontProviderQuery:字体名称必须和Google Fonts上的完全一致(注意大小写、空格,比如"Roboto Slab"不能写成"RobotoSlab")。
    • app:fontProviderCerts:这个是证书验证关键,无GMS设备报错很大概率是证书哈希配置错误。如果是测试阶段,可以暂时移除这个属性(不推荐正式环境),看看是否还抛异常;正式环境必须配置正确的证书数组。
  • 别忘了添加本地 fallback 字体:在XML里加<font>标签指定本地字体文件,这样下载失败时会自动 fallback,避免异常:
    <font-family xmlns:app="http://schemas.android.com/apk/res-auto">
        <!-- 远程字体配置 -->
        <app:fontProviderAuthority="com.google.android.gms.fonts"
            app:fontProviderPackage="com.google.android.gms"
            app:fontProviderQuery="Roboto"
            app:fontProviderCerts="@array/com_google_android_gms_fonts_certs"/>
        <!-- 本地 fallback 字体 -->
        <font app:fontStyle="normal" app:fontWeight="400" app:font="@font/roboto_regular"/>
    </font-family>
    

2. 替换同步调用为异步处理(避开v27 FontCallback)

你不能用v27的ResourcesCompat.FontCallback,可以改用v4 support库的FontsContract.FontRequestCallback,这是v24+ support库就有的API,兼容minSdk16:

  • 示例代码:
    // 构建FontRequest
    FontRequest fontRequest = new FontRequest(
        "com.google.android.gms.fonts",
        "com.google.android.gms",
        "Roboto", // 要下载的字体名称
        R.array.com_google_android_gms_fonts_certs // 证书数组
    );
    
    // 自定义回调处理结果
    FontsContract.FontRequestCallback fontCallback = new FontsContract.FontRequestCallback() {
        @Override
        public void onTypefaceRetrieved(Typeface typeface) {
            // 成功获取字体,在这里设置到TextView或其他控件
            textView.setTypeface(typeface);
        }
    
        @Override
        public void onTypefaceRequestFailed(int reason) {
            // 下载失败,使用本地 fallback 字体
            textView.setTypeface(Typeface.createFromAsset(getAssets(), "fonts/roboto_regular.ttf"));
        }
    };
    
    // 发起异步请求
    FontsContract.requestFont(
        getApplicationContext(),
        fontRequest,
        fontCallback,
        HandlerCompat.createAsync(Looper.getMainLooper()) // 确保回调在主线程执行
    );
    
    这种方式不会因为同步等待下载而抛出异常,完全避开了v27的API限制。

3. 处理无GMS设备的特殊情况

无GMS设备无法访问Google Fonts的provider,所以必须做兼容:

  • 在代码中判断设备是否有GMS服务,没有的话直接加载本地字体:
    private boolean hasGooglePlayServices(Context context) {
        GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
        int resultCode = apiAvailability.isGooglePlayServicesAvailable(context);
        return resultCode == ConnectionResult.SUCCESS;
    }
    
    // 使用时
    if (hasGooglePlayServices(this)) {
        // 发起远程字体请求
        requestRemoteFont();
    } else {
        // 直接加载本地字体
        textView.setTypeface(Typeface.createFromAsset(getAssets(), "fonts/roboto_regular.ttf"));
    }
    

4. 确认support库版本兼容性

确保你的support-compat库版本在v24.0.0到v26.1.0之间(符合minSdk16要求,同时避开v27),在build.gradle中配置:

implementation 'com.android.support:support-compat:26.1.0'

最后排查异常栈信息

如果以上步骤都没解决,一定要看具体的异常栈:

  • 要是Resources$NotFoundException:大概率是字体XML的provider属性写错了,或者本地 fallback 字体不存在。
  • 要是SecurityException:肯定是证书配置错误,检查证书数组里的哈希值是否正确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:29:27