【问题标题】:MediaMetadataRetriever FileNotFoundExceptionMediaMetadataRetriever FileNotFoundException
【发布时间】:2018-07-11 18:18:17
【问题描述】:

我正在构建一个应用程序,您首先可以在其中从手机中选择一个视频,然后该视频会在另一个活动中显示两次。也就是说,相同的视频显示在屏幕的左半边和右半边。 到目前为止我所做的:在第一个活动中,用户有一个按钮来选择视频:

gallybutton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(checkPermissionForReadExtertalStorage()) {
                    Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
                    startActivityForResult(i, 0);
                }
                else
                    requestPermissionForReadExtertalStorage();
            }
});

然后,当它被选中时,将启动第二个活动,将 uri 传递给所选视频:

public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            Uri selectedMediaUri = data.getData();
            if(selectedMediaUri != null) {
                Intent i = new Intent();
                i.setClass(this, VideoActivity.class);
                i.putExtra("uri", selectedMediaUri.toString());
                startActivity(i);
            }
        }
    }

由于我希望播放视频的方式而出现问题。在横向屏幕的情况下,我希望屏幕左半边的视频填充屏幕的高度,并在其一半保持纵横比的情况下居中裁剪。这是我尝试过的:

首先,我在 OnCreate 中恢复 uri 并获取其容器的尺寸,该容器占据了屏幕的所有左半部分:

String uriString = getIntent().getStringExtra("uri");
uri = Uri.parse(uriString);
final VideoView vv = findViewById(R.id.videoView);
final FrameLayout fl = findViewById(R.id.videoFrame);
    fl.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            setDimension(vv, fl.getWidth(), fl.getHeight());
            fl.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        }
    });

而且,如你所见,调用 setDimension 来设置 videoView 的维度:

private void setDimension(VideoView videoView, int width, int height) {
    // Adjust the size of the video
    // so it fits on the screen
    float videoProportion = getVideoProportion();
    float screenProportion = (float) height / (float) width;
    android.view.ViewGroup.LayoutParams lp = videoView.getLayoutParams();

    if (videoProportion < screenProportion) {
        lp.height= height;
        lp.width = (int) ((float) height / videoProportion);
    } else {
        lp.width = width;
        lp.height = (int) ((float) width * videoProportion);
    }
    videoView.setLayoutParams(lp);

    videoView.setVideoURI(uri);
    videoView.start();
}

当我调用 getVideoProportion() 时,问题就来了,它必须获取视频的“aspectRatio”(高度/宽度):

private float getVideoProportion(){
    MediaMetadataRetriever retriever = new MediaMetadataRetriever();
    retriever.setDataSource(uri.getPath());
    Bitmap bmp = retriever.getFrameAtTime();
    return (float)bmp.getHeight() / (float)bmp.getWidth();
}

因为这行retriever.setDataSource(uri.getPath());抛出 FileNotFoundException,这很奇怪,因为如果我调用

videoView.setVideoURI(uri);
videoView.start();

视频已播放,所以问题不在于文件不存在。 uri.getPath() 具有以下形式:/-1/2/content://media/external/video/media/6685/ORIGINAL/NONE/1567971923

【问题讨论】:

    标签: android video android-videoview aspect-ratio mediametadataretriever


    【解决方案1】:

    setDataSource()需要一个文件系统路径。您从 Intent.ACTION_PiCK 获得了一个内容方案。您可以检查自己 uri.getPath() 是否为您提供了一个不存在的文件系统路径。你应该使用uri.toString()。也告诉价值。但这也不会被接受,因为它是一个内容方案。

    【讨论】:

      猜你喜欢
      • 2019-07-20
      • 1970-01-01
      • 2013-08-07
      • 2015-02-18
      • 1970-01-01
      • 2012-03-31
      • 2016-06-04
      • 2015-06-11
      相关资源
      最近更新 更多