You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android中assets内CSS调用res/font字体失败及报错求助

在Android WebView中加载res/font字体失败的解决方案

我来帮你排查这个问题!你遇到的ClassNotFoundException: Didn't find class "com.turningpoint.turningpoint.staging.R$font"和字体加载失败,大概率是R类没有正确生成font相关引用,或者WebView访问资源的方式存在问题,试试下面这些针对性的方案:

1. 先确认资源和R类的正确性

  • 检查字体文件命名:res/font目录下的字体文件名必须符合Android资源命名规范——只能用小写字母、数字和下划线,你的jost_400_book.ttf是符合要求的,但如果有大写或特殊字符会导致R类无法生成引用。
  • 清理重建项目:有时候R类会因为缓存没有及时更新,点击Android Studio的Build > Clean Project,再执行Build > Rebuild Project,确保R$font类被正确生成。
  • 核对包名与构建变体:报错里的包名com.turningpoint.turningpoint.staging要和你当前使用的构建变体包名一致,多模块项目或不同环境的构建变体可能会导致R类路径不匹配。

2. 调整WebView的资源访问设置

WebView默认的设置可能限制了本地资源访问,添加以下配置:

WebSettings webSettings = webView.getSettings();
// 允许访问本地文件
webSettings.setAllowFileAccess(true);
// 允许从文件URL加载其他文件
webSettings.setAllowFileAccessFromFileURLs(true);
// 允许通用文件访问
webSettings.setAllowUniversalAccessFromFileURLs(true);

注意:Android 11及以上版本如果涉及外部文件访问需要额外权限,但访问res资源一般不需要,不过确保这些开关是开启的。

3. 换更稳定的字体引用方式

如果file:///android_res/的方式一直有问题,可以试试这几种替代方案:

方案一:将字体移到assets目录

把字体文件放到assets/fonts/目录下(没有就新建),然后在CSS里这样引用:

@font-face {
  font-family: jost;
  font-weight: normal;
  src: url("file:///android_asset/fonts/jost_400_book.ttf");
}

这种方式绕开了R类的依赖,很多开发者都用这种方法,稳定性更高。

方案二:Base64注入字体到HTML

通过Android代码把res/font里的字体转换成Base64字符串,直接注入到HTML的样式中,WebView可以直接解析:

// 读取res/font中的字体文件
InputStream fontStream = getResources().openRawResource(R.font.jost_400_book);
byte[] fontBytes = new byte[fontStream.available()];
fontStream.read(fontBytes);
fontStream.close();

// 转成Base64字符串
String fontBase64 = Base64.encodeToString(fontBytes, Base64.DEFAULT);

// 构建包含字体的HTML
String htmlContent = "<html>" +
        "<head>" +
        "<style>" +
        "@font-face { font-family: jost; src: url(data:font/truetype;base64," + fontBase64 + ") format('truetype'); }" +
        "body { font-family: jost; }" +
        "</style>" +
        "</head>" +
        "<body>你的HTML内容</body>" +
        "</html>";

// 加载HTML
webView.loadData(htmlContent, "text/html", "UTF-8");

方案三:使用官方推荐的WebViewAssetLoader(Android 7.0+)

这是Google推荐的安全访问本地资源的方式,避免file://的限制,步骤如下:

  1. 添加依赖到build.gradle:
implementation 'androidx.webkit:webkit:1.6.0'
  1. 配置AssetLoader和WebViewClient:
// 创建AssetLoader,映射/font/路径到res资源
WebViewAssetLoader assetLoader = new WebViewAssetLoader.Builder()
        .addPathHandler("/font/", new WebViewAssetLoader.ResourcesPathHandler(this))
        .build();

// 设置WebViewClient拦截请求
webView.setWebViewClient(new WebViewClient() {
    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
        return assetLoader.shouldInterceptRequest(request.getUrl());
    }
});
  1. 在CSS里用虚拟域名引用:
@font-face {
  font-family: jost;
  font-weight: normal;
  src: url("https://appassets.androidplatform.net/font/jost_400_book.ttf");
}

4. 查看WebView调试日志定位问题

开启WebView调试模式,在Chrome浏览器输入chrome://inspect连接你的设备,查看WebView的控制台日志,能看到字体加载失败的具体原因(比如404、格式不支持),帮助你更快定位问题。

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

火山引擎 最新活动