MediaMetadataRetriever FileNotFoundException

时间:2018-02-01 12:11:31

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

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

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);
            }
        }
    }

由于我希望播放视频的方式,问题出现了。屏幕处于横向方向时,我希望屏幕左半部分的视频能够填满屏幕的高度,并以半长宽比调整中心。以下是我尝试过的内容:

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

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()时必须得到&#34; aspectRatio&#34; (视频的高度/宽度):

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

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

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

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

1 个答案:

答案 0 :(得分:0)

uri.getPath()需要文件系统路径。您从Intent.ACTION_PiCK获取了一个内容方案。您可以检查一下uri.toString()为您提供了一个不存在的文件系统路径。您应该使用private void animateFlingInYAxis(View view) { FlingAnimation fling = new FlingAnimation(view, DynamicAnimation.SCROLL_Y); fling.setStartValue(0.9F); fling.setStartVelocity(0f); //fling.setMinValue(0.5F); fling.setFriction(0.2F); fling.start(); } 。告诉价值。但这也不会被接受,因为它是一种内容方案。