多媒体——视频——从视频库中选取视频

从视频库中选取视频

 

 

 

系统自带的相册既保存图片又保存视频,这意味着用户能够从中选择已有的视频。


打开视频库之前,需要指定数据类型为视频,相关代码代码示例如下:

 

 


Intent intent = new Intent(Intent.ACTION_GET_CONTENT);     // 创建一个内容获取动作的意图(准备跳到系统视频库)


intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);          // 是否允许多选


intent.setType("video/*");         // 类型为视频


startActivityForResult(intent, CHOOSE_CODE);                 // 打开系统视频库

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

============================================================================================================

 

 

 

 

 

 

 

 

 

 

 

 

 

 

布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btn_choose"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="打开视频库选取视频"
            android:textColor="@color/black"
            android:textSize="16sp" />

        <Button
            android:id="@+id/btn_combine"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="录像或从视频库选取"
            android:textColor="@color/black"
            android:textSize="16sp" />

    </LinearLayout>

    <TextView
        android:id="@+id/tv_video"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="5dp"
        android:textColor="@color/black"
        android:textSize="17sp" />

    <RelativeLayout
        android:id="@+id/rl_video"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:visibility="gone">

        <ImageView
            android:id="@+id/iv_video"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="fitCenter" />

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="fitCenter"
            android:src="@drawable/play_video" />
    </RelativeLayout>

</LinearLayout>

 

 

 

 

 

 

 

 

 

 

 

 

 

MediaUtil

 

package com.example.myapplication.util;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.os.Environment;
import android.util.Log;

import java.io.File;

@SuppressLint("DefaultLocale")
public class MediaUtil {
    private final static String TAG = "MediaUtil";

    // 格式化播放时长(mm:ss)
    public static String formatDuration(int milliseconds) {
        int seconds = milliseconds / 1000;
        int hour = seconds / 3600;
        int minute = seconds / 60;
        int second = seconds % 60;
        String str;
        if (hour > 0) {
            str = String.format("%02d:%02d:%02d", hour, minute, second);
        } else {
            str = String.format("%02d:%02d", minute, second);
        }
        return str;
    }

    // 获得音视频文件的缓存路径
    public static String getRecordFilePath(Context context, String dir_name, String extend_name) {
        String path = "";
        File recordDir = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString() + "/" + dir_name + "/");
        if (!recordDir.exists()) {
            recordDir.mkdirs();
        }
        try {
            File recordFile = File.createTempFile(DateUtil.getNowDateTime(), extend_name, recordDir);
            path = recordFile.getAbsolutePath();
            Log.d(TAG, "dir_name=" + dir_name + ", extend_name=" + extend_name + ", path=" + path);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return path;
    }

    // 获取视频文件中的某帧图片
    public static Bitmap getOneFrame(Context ctx, Uri uri) {
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        retriever.setDataSource(ctx, uri);
        // 获得视频的播放时长,大于1秒的取第1秒处的帧图,不足1秒的取第0秒处的帧图
        String duration = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
        Log.d(TAG, "duration="+duration);
        int pos = (Integer.parseInt(duration)/1000)>1 ? 1 : 0;
        // 获取指定时间的帧图,注意getFrameAtTime方法的时间单位是微秒
        return retriever.getFrameAtTime(pos * 1000 * 1000);
    }
}

 

 

 

 

 

 

 

 

 

FileUtil
package com.example.myapplication.util;

import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import android.util.Log;

import androidx.core.content.FileProvider;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

public class FileUtil {
    private final static String TAG = "FileUtil";

    // 把字符串保存到指定路径的文本文件
    public static void saveText(String path, String txt) {
        // 根据指定的文件路径构建文件输出流对象
        try (FileOutputStream fos = new FileOutputStream(path)) {
            fos.write(txt.getBytes()); // 把字符串写入文件输出流
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 从指定路径的文本文件中读取内容字符串
    public static String openText(String path) {
        String readStr = "";
        // 根据指定的文件路径构建文件输入流对象
        try (FileInputStream fis = new FileInputStream(path)) {
            byte[] b = new byte[fis.available()];
            fis.read(b); // 从文件输入流读取字节数组
            readStr = new String(b); // 把字节数组转换为字符串
        } catch (Exception e) {
            e.printStackTrace();
        }
        return readStr; // 返回文本文件中的文本字符串
    }

    // 把位图数据保存到指定路径的图片文件
    public static void saveImage(String path, Bitmap bitmap) {
        // 根据指定的文件路径构建文件输出流对象
        try (FileOutputStream fos = new FileOutputStream(path)) {
            // 把位图数据压缩到文件输出流中
            bitmap.compress(Bitmap.CompressFormat.JPEG, 80, fos);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 从指定路径的图片文件中读取位图数据
    public static Bitmap openImage(String path) {
        Bitmap bitmap = null; // 声明一个位图对象
        // 根据指定的文件路径构建文件输入流对象
        try (FileInputStream fis = new FileInputStream(path)) {
            // 从文件输入流中解码位图数据
            bitmap = BitmapFactory.decodeStream(fis);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bitmap; // 返回图片文件中的位图数据
    }

    // 检查文件是否存在,以及文件路径是否合法
    public static boolean checkFileUri(Context ctx, String path) {
        boolean result = true;
        File file = new File(path);
        if (!file.exists() || !file.isFile() || file.length() <= 0) {
            result = false;
        }
        try
        {
            Uri uri = Uri.parse(path); // 根据指定路径创建一个Uri对象

            // 兼容Android7.0,把访问文件的Uri方式改为FileProvider
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
            {

//                // 通过FileProvider获得文件的Uri访问方式
//                uri = FileProvider.getUriForFile(ctx,
//                        ctx.getPackageName()+".fileProvider", new File(path));
            }
        }
        catch (Exception e)   // 该路径可能不存在
        {
            e.printStackTrace();
            result = false;
        }
        return result;
    }

    // 把指定uri保存为存储卡文件
    public static void saveFileFromUri(Context ctx, Uri src, String dest) {
        try (InputStream is = ctx.getContentResolver().openInputStream(src);
             OutputStream os = new FileOutputStream(dest);) {
            int byteCount = 0;
            byte[] bytes = new byte[8096];
            while ((byteCount = is.read(bytes)) != -1){
                os.write(bytes, 0, byteCount);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 从content://media/external/file/这样的Uri中获取文件路径
    public static String getPathFromContentUri(Context context, Uri uri) {
        String path = uri.toString();
        if (path.startsWith("content://")) {
            String[] proj = new String[]{ // 媒体库的字段名称数组
                    MediaStore.Video.Media._ID, // 编号
                    MediaStore.Video.Media.TITLE, // 标题
                    MediaStore.Video.Media.SIZE, // 文件大小
                    MediaStore.Video.Media.MIME_TYPE, // 文件类型
                    MediaStore.Video.Media.DATA // 文件大小
            };
            try (Cursor cursor = context.getContentResolver().query(uri,
                    proj, null, null, null)) {
                cursor.moveToFirst(); // 把游标移动到开头
                if (cursor.getString(4) != null) {
                    path = cursor.getString(4);
                }
                Log.d(TAG, cursor.getLong(0) + " " + cursor.getString(1)
                        + " " + cursor.getLong(2) + " " + cursor.getString(3)
                        + " " + cursor.getString(4));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return path;
    }

}

 

 

 

 

 

 

 

主代码:

package com.example.myapplication;

import android.content.ClipData;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;

import com.example.myapplication.util.FileUtil;
import com.example.myapplication.util.MediaUtil;

public class MainActivity extends AppCompatActivity implements View.OnClickListener
{

    private final static String TAG = "VideoChooseActivity";
    private int CHOOSE_CODE = 3; // 只在视频库挑选图片的请求码
    private int COMBINE_CODE = 4; // 既可录像获得现场视频、也可在视频库挑选已有视频的请求码
    private TextView tv_video;
    private RelativeLayout rl_video;
    private ImageView iv_video;
    private Uri mVideoUri; // 视频文件的路径对象

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tv_video = findViewById(R.id.tv_video);
        rl_video = findViewById(R.id.rl_video);
        iv_video = findViewById(R.id.iv_video);

        findViewById(R.id.btn_choose).setOnClickListener(this);
        findViewById(R.id.btn_combine).setOnClickListener(this);
        findViewById(R.id.rl_video).setOnClickListener(this);
    }

    @Override
    public void onClick(View v)
    {
        if (v.getId() == R.id.btn_choose)
        {
            // 创建一个内容获取动作的意图(准备跳到系统视频库)

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

            intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "video/*");

            startActivityForResult(intent, CHOOSE_CODE); // 打开系统视频库
        }
        else if (v.getId() == R.id.btn_combine)
        {
            openSelectDialog(); // 打开选择对话框(要录像还是去视频库)
        }
        else if (v.getId() == R.id.rl_video)
        {
            String realPath = FileUtil.getPathFromContentUri(this, mVideoUri);

            // 创建一个内容获取动作的意图(准备跳到系统播放器)
            Intent intent = new Intent(Intent.ACTION_VIEW);

            intent.setDataAndType(Uri.parse(realPath), "video/*"); // 类型为视频

            startActivity(intent); // 打开系统的视频播放器
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent)
    {
        super.onActivityResult(requestCode, resultCode, intent);

        if (resultCode==RESULT_OK && requestCode==CHOOSE_CODE)  // 从视频库回来
        {
            if (intent.getData() != null)    // 选择一个视频
            {
                Uri uri = intent.getData(); // 获得已选择视频的路径对象
                showVideoFrame(uri); // 显示视频的某帧图片
            }
            else if (intent.getClipData() != null)     // 选择多个视频
            {
                ClipData videos = intent.getClipData(); // 获取剪切板数据

                if (videos.getItemCount() > 0)  // 至少选择了一个文件
                {
                    Uri uri = videos.getItemAt(0).getUri();   // 取第一个视频
                    showVideoFrame(uri);   // 显示视频的某帧图片
                }
            }
        }
        if (resultCode==RESULT_OK && requestCode==COMBINE_CODE)   // 从混合选择对话框回来
        {
            if (intent.getData() != null)  // 录像或者从视频库选择一个视频
            {
                Uri uri = intent.getData(); // 获得已选择视频的路径对象
                showVideoFrame(uri); // 显示视频的某帧图片
            }
        }
    }

    // 打开选择对话框(要录像还是去视频库)
    private void openSelectDialog()
    {
        // 声明摄像机的录像行为
        Intent recordIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
        Intent[] intentArray = new Intent[] { recordIntent };

        // 声明视频库的打开行为
        Intent videoIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

        videoIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "video/*");

        // 弹出含摄像机和视频库在内的列表对话框
        Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
        chooserIntent.putExtra(Intent.EXTRA_TITLE, "请录像或选择视频");
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
        chooserIntent.putExtra(Intent.EXTRA_INTENT, videoIntent);

        // 在页面底部弹出多种选择方式的列表对话框
        startActivityForResult(Intent.createChooser(chooserIntent, "选择视频"), COMBINE_CODE);
    }

    // 显示视频的某帧图片
    private void showVideoFrame(Uri uri)
    {
        mVideoUri = uri;
        tv_video.setText("你选中的视频地址为:"+uri.toString());
        rl_video.setVisibility(View.VISIBLE);

        // 获取视频文件的某帧图片
        Bitmap bitmap = MediaUtil.getOneFrame(this, uri);

        iv_video.setImageBitmap(bitmap); // 设置图像视图的位图对象
    }

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2022-10-15 14:57  小白龙白龙马  阅读(135)  评论(0编辑  收藏  举报