【问题标题】:How to pick a video from gallery in the newest API?如何在最新的 API 中从图库中挑选视频?
【发布时间】:2020-03-02 16:32:18
【问题描述】:

我正在尝试获取库中视频的路径,但 URI 给了我类似“/document/video:xxxx”的内容。当我使用 getPath() 时,我总是为空。

我设置了 FileProvider 并授予了所有权限,但没有任何效果。

    //Start intent

    Intent intent = new Intent();
    intent.setType("video/*");
    intent.setAction(Intent.ACTION_GET_CONTENT);
    startActivityForResult(Intent.createChooser(intent,"Select Video"), 1);

    //Turn URI to Path

    String getPath(Uri uri) {

    String[] projection = { MediaStore.Video.Media.DATA };
    Cursor cursor = getContentResolver().query(uri, projection, null, null, null);

    if (cursor != null) {
        // HERE YOU WILL GET A NULLPOINTER IF CURSOR IS NULL. THIS CAN BE, IF YOU USED OI FILE MANAGER FOR PICKING THE MEDIA
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    } else {
        return null;
    }

    }

【问题讨论】:

  • 您的帖子主题与您帖子中描述的问题无关。请适应。

标签: android video gallery


【解决方案1】:

这将允许您从图库中选择一个视频:

 Intent intent = new Intent(Intent.ACTION_PICK,   MediaStore.Video.Media.EXTERNAL_CONTENT_URI);

阅读this 了解有关intentsMediaStore 的更多信息。

【讨论】:

  • 我得到了正确的路径,但它给了我java.nio.file.AccessDeniedException: /storage/emulated/0/DCIM/Camera/VID_20191105_203230.mp4
  • 请添加存储依赖权限
  • 请点击此链接:stackoverflow.com/questions/47164357/… 它可能对您有所帮助。
【解决方案2】:

在 build.gradle(App) 中添加以下依赖项:

implementation 'com.droidninja:filepicker:2.2.0'

设置小部件clicklistener并创建文件数组imgbase64:

private var imageBase64 = ArrayList<File>()

imgVideo.setOnClickListener {
            val intent1 = Intent(this, VideoPickActivity::class.java)
            intent1.putExtra(ImagePickActivity.IS_NEED_CAMERA, false)
            intent1.putExtra(Constant.MAX_NUMBER, 1)
            intent1.putExtra(BaseActivity.IS_NEED_FOLDER_LIST, false)
            startActivityForResult(intent1, Constant.REQUEST_CODE_PICK_VIDEO)
        }

ovverride onActivityResult(),

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (data != null) {
            try {
                imageBase64.clear()
                when (requestCode) {
                    AppConstants.REQUEST_CODE_PICK_VIDEO -> {
                        if (resultCode == Activity.RESULT_OK && data != null) {
                            val list = data.getParcelableArrayListExtra<VideoFile>(AppConstants.RESULT_PICK_VIDEO)
                            for (item in list) {
                                imageBase64.add(File(item.path))
                                FILE_TYPE = 2
                            }
                        }
                    }
                }

            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
    }

创建多部分的surveyImagesParts数组,

val surveyImagesParts: Array<MultipartBody.Part?> = arrayOfNulls(imageBase64.size)
                for (index in imageBase64.indices) {
                    surveyImagesParts[index] = MultipartBody.Part.createFormData(
                        "message", imageBase64[index].name,
                        RequestBody.create(MediaType.parse("*/*"), imageBase64[index])
                    )
                }

在 api 调用中传递surveyImagesParts... 希望对您有所帮助...!

【讨论】:

    【解决方案3】:

    选择部分不是问题,您得到的是一个 URI。问题是默认情况下路径没有意义,因为您将无法访问它。

    MediaStore.Video.Media.DATA

    此常量在 API 级别 29 中已弃用。 应用程序可能没有直接访问此路径的文件系统权限。应用程序不应尝试直接打开此路径,而应使用 ContentResolver#openFileDescriptor(Uri, String) 来获得访问权限。

    https://developer.android.com/reference/android/provider/MediaStore.MediaColumns.html#DATA

    即使您能够获得路径,默认情况下您也无权使用它,您需要使用ContentResolver#openFileDescriptor(Uri, String) 获得访问权限。

    https://developer.android.com/reference/android/content/ContentResolver#openFileDescriptor(android.net.Uri,%20java.lang.String)

    我建议您阅读 https://developer.android.com/training/data-storage/files/external-scoped 以使用最新 API 上的存储

    更新:添加了如何处理 Intent 调用结果并获取可传递给大多数 Java IO 操作的 Java FileDescriptor 的示例。

    @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent resultData) {
            super.onActivityResult(requestCode, resultCode, resultData);
    
            Uri uri = null;
    
            // The `requestCode` was `1` in the code in the question
            if (requestCode == 1 && resultCode == RESULT_OK) {
                if (resultData != null) {
                    uri = resultData.getData();
                    try {
                        // Open for Read
                        ParcelFileDescriptor pfd =
                                this.getContentResolver().
                                        openFileDescriptor(uri, "r");
    
                        FileDescriptor fileDescriptor = pfd.getFileDescriptor();
    
                        // Now do something fileDescriptor like read the input Stream
                        FileInputStream fileInputStream =
                                new FileInputStream(
                                        fileDescriptor);
    
                        ....
    
    
                    } catch (Exception e) {
                        // Do something with Exceptions
                    }
                }
            }
        }
    
    

    【讨论】:

    • 更新添加了一些关于如何获取FileDescriptor的示例代码
    • 再次感谢您,文件应该是视频,我可以将这些字节写入新文件(副本)吗?
    • 是的,您可以写入文件,但根据您要保存的位置,您可能需要使用 MediaStoreStorage Access FrameworkACTION_CREATE_DOCUMENT 但同样您将无法访问路径这些方法
    • 我要把它保存到 getExternalFilesDir()。我该怎么做?
    • 我建议你再问一个问题,因为写文件超出了这个问题的范围
    【解决方案4】:

    在清单文件中使用以下权限,如果您的设备是棉花糖及以上,则还要授予运行时权限。

             <uses-permission  android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-09
      • 1970-01-01
      • 1970-01-01
      • 2015-04-02
      相关资源
      最近更新 更多