最近要做一个 Android上的录像功能,由于之前做拍照功能完全是用自定义方式,太麻烦。故这次决定直接调用系统相机来录像。
一、添加权限
首先,添加必要的权限
<!-- 授予该程序使用摄像头的权限 -->
<uses-permission android:name="android.permission.CAMERA"/>
<!-- 授予该程序使用麦克疯的权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-feature
android:glEsVersion="0x00020000"
android:required="true" />
二、添加运行时权限
Android api23以上在代码中申请运行时权限,允许访问相机、录音、文件读取等。
int checkCallPhonePermission = ContextCompat.checkSelfPermission(ActivityAudio.this, Manifest.permission.CAMERA);
if(checkCallPhonePermission != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(ActivityAudio.this, new String[]{Manifest.permission.CAMERA}, 1);
return;
}
三、调用相机录像
录视频前必须确认文件夹存在,否则写入异常
public void takeVideo(View view) {
System.out.println("开始录像");
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
//录视频前必须确认文件夹存在,否则写入异常
String videoPath = Environment.getExternalStorageDirectory() + "/Video";//设置照片保存路径
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File file = new File(videoPath, "MP4_" + timeStamp + ".mp4");
path = file.getAbsolutePath();
System.out.println("开始录像:"+path);
//使用文件提供者获取路径URL
Uri contentUri = OpenFileUtil.getUriForFile(this,file);
//设置传递参数
intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);
//用于控制录制视频的质量,只有两种;0——低质量;1——高质量
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
//允许记录的最长时间(以 秒 为单位) 例如:限制为60S
intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 20);
//允许的最大大小(以 B 为单位) 例如:限制大小为100M
intent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, 1024L * 1024 * 100);
startActivityForResult(intent, REQUEST_VIDEO_CAPTURE);
}
也可以不设置参数,直接调,这样生成的视频就在媒体文件夹目录下:
public void takeVideo(View view) {
Intent intent=new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent, REQUEST_VIDEO_CAPTURE);
}
}
注意,SDK24以上,获取文件URI的方式有变化:
public static Uri getUriForFile(Context context, File file) {
if (context == null || file == null) {
throw new NullPointerException();
}
Uri uri;
if (Build.VERSION.SDK_INT >= 24) {
uri = FileProvider.getUriForFile(context.getApplicationContext(), context.getPackageName()+".fileprovider", file);
} else {
uri = Uri.fromFile(file);
}
return uri;
}
具体可以查看我的另一篇:
2024-07-16升级问题:调用自带软件打开文件时 android.os.FileUriExposedException-CSDN博客
四、参数说明
- MediaStore.EXTRA_OUTPUT:设置媒体文件的保存路径。
- MediaStore.EXTRA_VIDEO_QUALITY:设置视频录制的质量,0为低质量,1为高质量。
- MediaStore.EXTRA_DURATION_LIMIT:设置视频最大允许录制的时长,单位为秒。
- MediaStore.EXTRA_SIZE_LIMIT:指定视频最大允许的尺寸,单位为byte。
关于参数的官方文档:
MediaStore | Android Developershttps://developer.android.google.cn/reference/android/provider/MediaStore#EXTRA_VIDEO_QUALITY
关于MediaStore.EXTRA_VIDEO_QUALITY:低质量时,拍出来的结果非常模糊;高质量时占用空间较大。
五、页面回调处理
在调用页面增加onActivityResult的回调处理函数,在录像完成后对结果进行处理:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode){
case OnClick_TakeVideo.REQUEST_CODE_TAKE_VIDEO:
File curfile = OnClick_TakeVideo.pCurMP4;
if(curfile!=null){
if(curfile.exists()){
long fileSize = curfile.length();
if(fileSize<10){
curfile.delete();
Toast.makeText(this, "已取消,视频大小:"+ ToolFormatOper.unitAuto_2(fileSize),Toast.LENGTH_LONG).show();
}
else {
OnClick_TakeVideo.savePoint2DB(this);
Toast.makeText(this, "完成,视频大小:"+ ToolFormatOper.unitAuto_2(fileSize),Toast.LENGTH_LONG).show();
}
}
}
break;
case OnClick_TakeCapture.REQUEST_CODE_TAKE_CAPTURE:
File fileCapture = OnClick_TakeCapture.pCurPicture;
if(fileCapture!=null){
if(fileCapture.exists()){
long fileSize = fileCapture.length();
if(fileSize<10){
fileCapture.delete();
Toast.makeText(this, "已取消,照片大小:"+ ToolFormatOper.unitAuto_2(fileSize),Toast.LENGTH_LONG).show();
}
else {
Toast.makeText(this, "完成,照片大小:"+ ToolFormatOper.unitAuto_2(fileSize),Toast.LENGTH_LONG).show();
}
}
}
break;
default:
break;
}
}
总结:
调用系统相机优点: 调用方便简单,开发量少,适用于快速实现功能。界面简单,无需自己构建复杂的拍摄界面进行处理,方便易于使用,比较美观,功能相对完善。毕竟都是系统自带的;
调用系统相机缺点: 无法个性化参数设置。系统相机其实相当于一个已经封装好的工具,可设置的参数相对有限,比如无法自定义具体的分辨率,文件要么清晰但占用大空间,要么低画质模糊不清。无法获取拍摄时的方位角,自定义拍摄界面可以方便得调用硬件传感器,计算拍摄瞬间的方位角等信息,但调用系统界面相机,就没办法在系统界面去获取这些信息了。