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


    从视频库中选取视频

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


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


    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); // 设置图像视图的位图对象
        }
    
    }

     

     

  • 相关阅读:
    CSS发布时间
    1CSS简介
    CSS 样式的优先级(重要,一定要理解)
    css为什么叫层叠样式表
    Django学习手册
    Django学习手册
    Django学习手册
    Django学习手册
    Django学习手册
    Django学习手册
  • 原文地址:https://www.cnblogs.com/xiaobaibailongma/p/16794229.html
Copyright © 2020-2023  润新知