MediaMetadataRetriever FileNotFoundException
Я создаю приложение, в котором вы можете сначала выбрать видео с телефона, а затем оно будет показано дважды в другом упражнении. То есть одно и то же видео показывается в левой половине и в правой половине экрана. Что я сделал так далеко: В первом упражнении у пользователя есть кнопка для выбора видео:
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(), которая должна получить "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
1 ответ
setDataSource()
ожидает путь к файловой системе. Вы получили схему содержимого от Intent.ACTION_PiCK. Вы можете проверить, что uri.getPath()
дает вам несуществующий путь к файловой системе. Вы должны использовать uri.toString()
, Скажите значение тоже. Но это тоже не будет принято, так как это контент-схема.