Android Kotlin中指定目录打开文件管理器并过滤无关应用
解决方案
问题原因分析
- 无关应用弹出:原代码使用
ACTION_VIEW+type="*/*",这个组合会匹配所有能处理任意类型数据的应用(包括邮件、社交类APP),而非仅文件管理器。 - 打开错误目录:
Uri.fromFile()生成的file://Uri在Android 10+的Scoped Storage机制下存在权限限制,且多数文件管理器对这类Uri的处理逻辑不一致,导致默认跳转到Downloads目录。
修正后的代码实现
以下是适配Android 10+的正确代码,既能精准定位到Documents目录,又能仅显示文件管理器类应用:
import android.content.Intent import android.content.pm.PackageManager import android.net.Uri import android.os.Build import android.os.Environment import android.provider.DocumentsContract import android.provider.MediaStore import androidx.appcompat.app.AppCompatActivity fun AppCompatActivity.openDocumentsDirectory() { // 构建打开目录的Intent,使用SAF(Storage Access Framework) val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply { // 指定初始跳转目录为Documents val documentsUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { // Android 10+ 用SAF的方式获取Documents目录Uri MediaStore.Files.getContentUri("external").buildUpon() .appendPath(Environment.DIRECTORY_DOCUMENTS) .build() } else { // 兼容Android 9及以下,使用旧方式(注意:Android 10+已废弃) Uri.fromFile(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)) } putExtra(DocumentsContract.EXTRA_INITIAL_URI, documentsUri) // 添加持久化权限,后续可直接访问该目录 flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION } // 过滤仅保留文件管理器类应用 val packageManager = packageManager val resolveInfos = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY) val filteredIntents = mutableListOf<Intent>() resolveInfos.forEach { resolveInfo -> val componentName = resolveInfo.activityInfo.componentName val targetIntent = Intent(intent).apply { setComponent(componentName) } filteredIntents.add(targetIntent) } // 创建选择器,只显示过滤后的应用 if (filteredIntents.isNotEmpty()) { val chooser = Intent.createChooser(filteredIntents.removeAt(0), "选择文件管理器") chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, filteredIntents.toTypedArray()) startActivity(chooser) } }
关键说明
- 使用SAF机制:
ACTION_OPEN_DOCUMENT_TREE是Android官方推荐的目录访问方式,仅文件管理器类应用会注册该Intent的处理逻辑,从根源避免无关应用出现。 - 指定初始目录:通过
DocumentsContract.EXTRA_INITIAL_URI传递Documents目录的SAF Uri,确保文件管理器直接跳转到目标目录。 - 应用过滤:通过
queryIntentActivities获取所有能处理该Intent的应用,再构建仅包含这些应用的选择器,进一步确保只显示文件管理器。
内容的提问来源于stack exchange,提问作者Androidew1267
相关产品推荐
相关产品推荐

