最近要做一个 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-featureandroid: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);//使用文件提供者获取路径URLUri contentUri = OpenFileUtil.getUriForFile(this,file);//设置传递参数intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);//用于控制录制视频的质量,只有两种;0——低质量;1——高质量intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);//允许记录的最长时间(以 秒 为单位) 例如:限制为60Sintent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 20);//允许的最大大小(以 B 为单位) 例如:限制大小为100Mintent.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;}
}
总结:
调用系统相机优点: 调用方便简单,开发量少,适用于快速实现功能。界面简单,无需自己构建复杂的拍摄界面进行处理,方便易于使用,比较美观,功能相对完善。毕竟都是系统自带的;
调用系统相机缺点: 无法个性化参数设置。系统相机其实相当于一个已经封装好的工具,可设置的参数相对有限,比如无法自定义具体的分辨率,文件要么清晰但占用大空间,要么低画质模糊不清。无法获取拍摄时的方位角,自定义拍摄界面可以方便得调用硬件传感器,计算拍摄瞬间的方位角等信息,但调用系统界面相机,就没办法在系统界面去获取这些信息了。