如何使用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
相关产品推荐
相关产品推荐

