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

如何使用Android存储访问框架访问TTF字体文件目录?

使用Android存储访问框架访问TTF字体目录的方案

核心思路

Android存储访问框架(SAF)中,要访问目录而非单个文件,关键是获取目录的DocumentFile实例,之后就能遍历目录内的TTF文件或直接操作文件。

具体步骤

1. 发起目录选择请求

通过ACTION_OPEN_DOCUMENT_TREE Intent让用户选择目标目录,代码示例:

val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
startActivityForResult(intent, REQUEST_CODE_PICK_DIR)
  • FLAG_GRANT_PERSISTABLE_URI_PERMISSION用于重启App后保留访问权限,避免重复请求用户授权。

2. 处理目录选择结果

在onActivityResult(或Jetpack的Activity Result API)中获取目录Uri,转为DocumentFile:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == REQUEST_CODE_PICK_DIR && resultCode == Activity.RESULT_OK) {
        data?.data?.let { treeUri ->
            // 持久化权限
            contentResolver.takePersistableUriPermission(
                treeUri,
                Intent.FLAG_GRANT_READ_URI_PERMISSION
            )
            // 获取目录的DocumentFile实例
            val dirDocument = DocumentFile.fromTreeUri(this, treeUri)
            // 遍历目录内的TTF文件
            dirDocument?.listFiles()?.forEach { file ->
                if (file.name?.endsWith(".ttf", ignoreCase = true) == true) {
                    // 处理单个TTF文件,比如加载字体
                    contentResolver.openFileDescriptor(file.uri, "r")?.use { fd ->
                        val typeface = Typeface.createFromFileDescriptor(fd.fileDescriptor)
                    }
                }
            }
        }
    }
}

如果用Activity Result API(推荐替代onActivityResult):

val pickDirLauncher = registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { treeUri ->
    treeUri ?: return@registerForActivityResult
    contentResolver.takePersistableUriPermission(
        treeUri,
        Intent.FLAG_GRANT_READ_URI_PERMISSION
    )
    val dirDocument = DocumentFile.fromTreeUri(this, treeUri)
    // 后续遍历处理同上
}

// 触发目录选择
pickDirLauncher.launch(null)

3. 加载目录内的TTF字体

拿到单个TTF文件的Uri后,可通过两种方式加载字体:

// 方式1:使用FileDescriptor
contentResolver.openFileDescriptor(file.uri, "r")?.use { fd ->
    val typeface = Typeface.createFromFileDescriptor(fd.fileDescriptor)
}

// 方式2:使用FontsContract(适合自定义字体家族)
val fontRequest = FontRequest("", "", file.uri.toString())
val fontFamily = FontsContract.buildFontFamily(this, listOf(fontRequest))

注意事项

  • 必须由用户手动选择目录,SAF不允许静默访问外部存储目录,这是Android隐私规范要求。
  • 持久化权限后,需将目录Uri保存到SharedPreferences等本地存储,下次启动App时直接复用,无需再次请求用户选择。
  • 若需写入目录(比如从assets复制字体到外部目录),要在Intent中添加FLAG_GRANT_WRITE_URI_PERMISSION,并在takePersistableUriPermission时一并申请读写权限。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 00:35:11