Android 11操作\打开\文档\树:将初始URI设置为文档文件夹

Android 11操作\打开\文档\树:将初始URI设置为文档文件夹,android,android-11,scoped-storage,Android,Android 11,Scoped Storage,使用Android 11中的作用域存储模型,我想让用户能够选择一个文件夹,从documents文件夹开始: val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, ??? ); startActivityForResult(intent, OPEN_DIRECTORY

使用Android 11中的作用域存储模型,我想让用户能够选择一个文件夹,从documents文件夹开始:

          val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
          intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI,    ???     );
          startActivityForResult(intent, OPEN_DIRECTORY_REQUEST_CODE,null);

问题是,如何生成手机文档文件夹的正确URI?(它位于root/)在官方文档中,没有给出示例。我真的希望所有标准位置都有一些整洁的常量

如何生成手机文档文件夹的正确URI

测试日期:

  • 小米M2102J20SI
  • 模拟器像素4 XL API 30
  • 函数
    askPermission()
    打开目标目录

    @RequiresApi(Build.VERSION_CODES.Q)
    private fun askPermission() {
        val storageManager = application.getSystemService(Context.STORAGE_SERVICE) as StorageManager
        val intent =  storageManager.primaryStorageVolume.createOpenDocumentTreeIntent()
    
        val targetDirectory = "WhatsApp%2FMedia%2F.Statuses" // add your directory to be selected by the user
        var uri = intent.getParcelableExtra<Uri>("android.provider.extra.INITIAL_URI") as Uri
        var scheme = uri.toString()
        scheme = scheme.replace("/root/", "/document/")
        scheme += "%3A$targetDirectory"
        uri = Uri.parse(scheme)
        intent.putExtra("android.provider.extra.INITIAL_URI", uri)
        startActivityForResult(intent, REQUEST_CODE)
    }
    
    函数
    readSDK30()
    用于从
    Uri

      private fun readSDK30(treeUri: Uri) {
            val tree = DocumentFile.fromTreeUri(this, treeUri)!!
    
            thread {
                val uriList  = arrayListOf<Uri>()
                listFiles(tree).forEach { uri ->
                     
                    // Collect all the Uri from here
                }
                
            }
        }
    
    fun listFiles(folder: DocumentFile): List<Uri> {
                return if (folder.isDirectory) {
                    folder.listFiles().mapNotNull { file ->
                        if (file.name != null) file.uri else null
                    }
                } else {
                    emptyList()
                }
            }
    

    我们将制作从
    StorageManager..getPrimaryStorageVolume().createOpenDocumentTreeContent()获取的
    INITIAL\u URI


    所有的功劳都归于blackapps

    以下是Kotlin语言中的相同代码:

    if(android.os.Build.VERSION.SDK\u INT>=android.os.Build.VERSION\u CODES.Q){
    val sm=作为StorageManager的getSystemService(Context.STORAGE\u服务)
    intent=sm.primaryStorageVolume.createOpenDocumentTreeIntent()
    //字符串startDir=“Android”;
    //String startDir=“下载”//在Android 11设备上不可选择
    //字符串startDir=“DCIM”;
    //字符串startDir=“DCIM/Camera”;//替换“/”,%2F
    //字符串startDir=“DCIM%2FCamera”;
    val startDir=“文件”
    var uriroot=intent.getParcelableExtra(“android.provider.extra.INITIAL\u URI”)//获取系统根URI
    var scheme=uriroot.toString()
    Log.d(“调试”,“初始URI方案:$scheme”)
    scheme=scheme.replace(“/root/”,“/document/”)
    scheme+=%3A$startDir”//将uri更改为文档文件夹
    uriroot=Uri.parse(scheme)
    intent.putExtra(“android.provider.extra.INITIAL_URI”,uriroot)//将更改后的URI提供给intent
    Log.d(“调试”,“uri:$uriroot”)
    startActivityForResult(意图、打开目录、请求代码);
    }
    

    正如一些评论者所提到的,这段代码将来可能会中断并且不起作用,这是事实。然而,考虑到Android的过去,他们将每隔一年改变一次存储API。

    “问题是,我如何才能为手机的文档文件夹生成一个合适的URI?”--好的,没有选择,抱歉
    EXTRA_INITIAL_URI
    被设计为一些
    URI
    ,您以前从
    ACTION\u OPEN\u DOCUMENT_TREE
    @Commonware中获得,请查看我的答案。您正在对
    URI
    格式进行假设;这些假设在Android版本中可能并不稳定。非常感谢,我会尝试一下。如果它适用于大多数手机,只要它不会在其他手机上崩溃就足够了。这是一种“总比没有好”的方法。这在android-9及以下版本中有效吗?
    if(android.os.Build.VERSION.SDK\u INT>=android.os.Build.VERSION\u CODES.Q)
    谢谢,这基本上告诉了如何使用作用域存储来创建随机启动目录。谢谢你的干净代码。不幸的是,我的问题是如何将作用域存储用于用户不能自行选择的固定起始目录。@Kenobi,如何使用操作\打开\文档\树。。。。。。。。它与作用域存储无关……请在顶部提到的帖子上再次发布您的Kotlin代码“问题已经在这里有了答案:'此页面的访问者将不再查看,所以我认为您的代码在那里更好。
    fun listFiles(folder: DocumentFile): List<Uri> {
                return if (folder.isDirectory) {
                    folder.listFiles().mapNotNull { file ->
                        if (file.name != null) file.uri else null
                    }
                } else {
                    emptyList()
                }
            }
    
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q)
            {
                StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
    
                Intent intent = sm.getPrimaryStorageVolume().createOpenDocumentTreeIntent();
                //String startDir = "Android";
                //String startDir = "Download"; // Not choosable on an Android 11 device
                //String startDir = "DCIM";
                //String startDir = "DCIM/Camera";  // replace "/", "%2F"
                //String startDir = "DCIM%2FCamera";
                String startDir = "Documents";
    
                Uri uri = intent.getParcelableExtra("android.provider.extra.INITIAL_URI");
    
                String scheme = uri.toString();
    
                Log.d(TAG, "INITIAL_URI scheme: " + scheme);
    
                scheme = scheme.replace("/root/", "/document/");
    
                scheme += "%3A" + startDir;
    
                uri = Uri.parse(scheme);
    
                intent.putExtra("android.provider.extra.INITIAL_URI", uri);
    
                Log.d(TAG, "uri: " + uri.toString());
    
                ((Activity) context).startActivityForResult(intent, REQUEST_ACTION_OPEN_DOCUMENT_TREE);
    
                return;
            }