Android - 視頻的錄製保存以及視頻列表查看

一、綜述

之前做了一個 Android 應用,有一個功能是:用戶錄製視頻並保存到本地,然後可以查看在當前 APP 中錄製的視頻並進行一些“上傳”或“刪除”操作。
這裏主要有兩個功能,首先要錄製視頻然後保存到一個特定的文件夾,這個文件夾就用來存放本應用中錄製的視頻。然後可以將這個文件夾中的所有文件以列表的形式展示給用戶看,並附帶縮略圖。
剛開始的時候我想自己寫一個錄製的功能,無奈本領不濟,左改右改都不好用,要麼是視頻被拉伸,要麼是錄製時不清晰,所以最後還是決定使用手機自帶的錄像功能,現在把該模塊的 Demo 拿上來與大家交流一下。

Demo

二、代碼解析

這裏的代碼解析只貼了一些重要代碼,想要完整代碼可以下載上面的 Demo 運行。

1. 錄製及保存

從代碼中我們看出,我們點擊“錄製”按鈕,會首先生成一個文件的 uri,這個 uri 就代表將要錄製的視頻文件,uri 裏有這個文件保存的文件夾以及這個文件的名字。
之後我們通過隱式 Intent 啓動系統的錄像功能,並將文件的 uri 傳入,文件就能根據設置的 uri 保存到指定文件夾。

/**
 * 點擊錄製視頻,調用系統播放器開始錄像
 */
main_button_record.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        try {
            fileUri = Uri.fromFile(createMediaFile());
        } catch (IOException e) {
            e.printStackTrace();
        }

        Intent intent = new Intent();
        intent.setAction("android.media.action.VIDEO_CAPTURE");
        intent.addCategory("android.intent.category.DEFAULT");

        intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);  // 設置視頻文件的名字
        intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); // 設置視頻質量爲高
        startActivityForResult(intent, CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE);
    }
});

/**
 * 創建一個文件的 uri,供視頻錄製完保存
 */
private File createMediaFile() throws IOException {
    // 如果 SD 卡存在,則在外部存儲建立一個文件夾用於存放視頻
    if ((Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))) {
        // 選擇自己的文件夾
        String path = Environment.getExternalStorageDirectory().getPath();
        // Constants.video_url 是一個常量,代表存放視頻的文件夾
        File mediaStorageDir = new File(path + Constants.video_url);
        if (!mediaStorageDir.exists()) {
            if (!mediaStorageDir.mkdirs()) {
                Log.e("TAG", "文件夾創建失敗");
                return null;
            }
        }

        // 文件根據當前的毫秒數給自己命名
        String timeStamp = String.valueOf(System.currentTimeMillis());
        timeStamp = timeStamp.substring(7);
        String imageFileName = "V" + timeStamp;
        String suffix = ".mp4";
        File mediaFile = new File(mediaStorageDir + File.separator + imageFileName + suffix);
        return mediaFile;
    }
    return null;
}

2. 查看視頻文件列表

這裏有兩個重要方法。
一個是獲取文件的列表,在這個方法中,我們先判斷外部 SD 卡是否可用,如果可用,就獲取之前保存文件的目錄下的所有文件。文件的屬性中有一個最後修改時間,我們就拿來用作文件的發佈時間。
第二個方法是用於獲取視頻的縮略圖的,這個方法需要文件的路徑並通過路徑獲取縮略圖。路徑 filePath 使用 files.getPath() 或 files.getAbsolutePath() 都可以。

/**
 * 獲取文件列表
 */
public void GetVideoFiles(){
    if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
        // 獲取該文件夾下的所有文件
        String path = Environment.getExternalStorageDirectory().getPath();
        File mediaStorageDir = new File(path + Constants.video_url);
        File[] files = mediaStorageDir.listFiles();

        if (files != null && files.length > 0) {
            for(int i = 0; i < files.length; i++){
                VideoItem videoItem = new VideoItem();
                videoItem.setVideoName(files[i].getName());
                String publish_time = new SimpleDateFormat("yyyy年MM月dd日").format(files[i].lastModified());
                videoItem.setTime(publish_time);
                videoItem.setBitmap(getVideoThumbnail(files[i].getAbsolutePath()));
                mVideoItems.add(videoItem);
            }
        } else {
            Toast.makeText(this, "沒有視頻文件!", Toast.LENGTH_SHORT).show();
        }
    }
}

/**
 * 根據視頻文件的路徑獲取視頻的縮略圖
 * filePath 使用 files.getPath() 或 files.getAbsolutePath() 都可以
 */
public Bitmap getVideoThumbnail(String filePath) {
    Bitmap bitmap = null;
    MediaMetadataRetriever retriever = new MediaMetadataRetriever();
    try {
        retriever.setDataSource(filePath);
        bitmap = retriever.getFrameAtTime();
    } catch(IllegalArgumentException e) {
        e.printStackTrace();
    } catch (RuntimeException e) {
        e.printStackTrace();
    } finally {
        try {
            retriever.release();
        } catch (RuntimeException e) {
            e.printStackTrace();
        }
    }
    return bitmap;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章