参考:
使用FileProvider解决Android 7(N)以上FileUriExposedException
Android 中使用MediaRecorder进行录像详解(视频录制)
Android使用MediaRecorder和Camera实现视频录制及播放功能整理
Android自定义录像功能
Android自定义视频录制
Android Camera2 教程 · 第一章 · 概览
Android Camera2 教程 · 第二章 · 开关相机
Android Camera2 教程 · 第三章 · 预览
Android Camera2 教程 · 第四章 · 拍照
Android项目小结——可对焦的视频录制(MediaRecorder与TextureView实现)
android–调用系统相机拍照,显示并保存照片
几种流行的视频编码比较(入门级别)
【视频编码格式】全面解析
[转] 浅谈视频基础知识、视频编码、压制
视频录制有两种方式:
- 调用手机的摄像功能,但是这样就产生问题了,现在的手机摄像头像素越来越高,拍摄效果越来越清晰,很多都达到了720p甚至是1080p,这样短暂的10s时长内存占用就达到了40M,显然这样是不可能的,并且intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);这行代码设置视频质量,只有0和1两档,0视频体积小很模糊,1视频高清体积太大
- 利用安卓自带的MediaRecorder来录制视频,并制定视频保存路径,并且可以通过Camera来播放录制的视频,可以自定义清晰度等各种参数
获取权限:不论哪种方式都要这一块
- 在AndroidManifest.xml文件中添加权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" /> <!-- 摄像头权限 -->
<uses-feature android:name="android.hardware.camera" /> <!-- 需要有摄像头 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 写入权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
- 代码中动态获取权限
//获取权限
private void getPermission(){
Log.e("getPermission", "获取权限逻辑判断");
if (Build.VERSION.SDK_INT >= 23) {
int REQUEST_CODE_CONTACT = 101;
String[] permissions = {
Manifest.permission.RECORD_AUDIO,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.CAMERA,};
//验证是否许可权限
for (String str:permissions) {
if (this.checkSelfPermission(str) != PackageManager.PERMISSION_GRANTED) {
//申请权限
this.requestPermissions(permissions,REQUEST_CODE_CONTACT);
Log.e("getPermission", "申请获取权限");
return;
}
}
}
}
一. 调用系统相机
使用FileProvider设置文件路径
- AndroidManifest.xml文件中添加provider节点.
可参考官网FileProvider的使用
<!--android:name是FileProvider组件的完整类名。
android:authorities是域名,为了保证唯一性,通常是你的应用包名+fileprovider。
android:exported 设置false,因为你不需要暴露它。
android:grantUriPermissions设置true,表示允许你可以对文件授予临时权限。
-->
<provider
android:authorities="com.sdxzt.xueliangapp.provider"
android:name="androidx.core.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths">
</meta-data>
</provider>
- 需要新建一个xml文件,在res/xml文件夹下新建file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<root-path
name="root_path"
path="." />
<files-path
name="my_videos"
path="videos" />
</paths>
- 在代码中
Uri fileUri = null;
try {
fileUri = FileProvider.getUriForFile(getApplicationContext(),"com.sdxzt.xueliangapp.provider",createMediaFile());
} catch (IOException e) {
e.printStackTrace();
}
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
//可以调用 Context.grantUriPermission 方法来给Uri赋予权限,调用 revokeUriPermission() 函数来撤销权限,也可以通过 Intent.setFlags() 的方式来赋予临时访问权限
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
private String getSDPath() {
File sdDir = null;
//判断sd卡是否存在
boolean sdCardExist = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
if (sdCardExist) {
sdDir = Environment.getExternalStorageDirectory();//获取根目录
return sdDir.toString();
}
return null;
}
源码
package com.example.test.video_and_audio;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.FileProvider;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import com.example.test.R;
import java.io.File;
import java.io.IOException;
public class Video2Activity extends AppCompatActivity {
private Button video;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreat