音视频的整个开发流程抛开技术层面业务逻辑来讲当然是音视频采集,这也是整个音视频开发的第一步,当我们有数据源之后才会进行下一不的操作,
在手机端首先想到的肯定是摄像头以及麦克风,这篇文章是先看一下手机自带的相机在工作中的使用方法
- 选取头像
- 聊天发送即时图片
- 发送朋友圈等等
这些是我们不需要从数据源头来处理的,手机相机完全可以满足需求
[toc]
一、 使用相机拍照
1.1 申请权限
<uses-permission android:name="android.permission.CAMERA" />
// 麦克风权限
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!--表示该应用必须在有相机功能的设备上才能使用-->
<uses-feature android:name="android.hardware.camera" />
Android 6.0 以上系统需要在代码中进行动态申请权限
动态权限申请可以使用:
implementation 'com.yanzhenjie:permission:2.0.3'
在需要使用的地方或者统一一个位置进行申明(因为动态权限的申请方式就那几个步骤,没必要自己进行封装)
AndPermission.with(this)
.runtime()
.permission(Permission.Group.STORAGE)
.permission(Permission.Group.CAMERA)
.onGranted {
// 次回调中进行逻辑操作
thread {
copyFromAssetcFiles()
}
}.start()
1.2 调用相机
Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
/**
* startActivityForResult() 方法受调用 resolveActivity()(返回可处理 Intent 的第一个 Activity 组件)的条件保护。
* 执行此检查非常重要,因为如果您使用任何应用都无法处理的 Intent 调用 startActivityForResult(),您的应用就会崩溃。所以只要结果不是 Null,
* 就可以放心使用 Intent。
*/
takePictureIntent.resolveActivity(packageManager)?.also {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
}
}
1.3 使用
// 拍完照之后会返回data 转换成bitmao 进行使用
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
val imageBitmap = data?.extras?.get("data") as Bitmap
cameraIv.setImageBitmap(imageBitmap)
}
}
完成了一个完整的拍照功能,是不是感觉缺了什么?是的我们需要将拍照的照片进行保存或者拿到他的本地地址
1.4 设定一个路径并且拍照
- 创建文件
@Throws(IOException::class)
fun createImageFile(): File {
val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
val externalFilesDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES)
return File.createTempFile(
"JPEG_${timeStamp}_", //前缀
".jpg", //后缀
externalFilesDir //路径
).apply {
// 用于预览
currentPhotoPath = absolutePath
}
}
- 调用相机并传入路径
Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
try {
takePictureIntent.resolveActivity(packageManager)?.also {
val photoFile: File? = try {
createImageFile()
} catch (ex: IOException) {
LogUtils.e("create File error ${ex.message}")
null
}
photoFile?.also {
val photoURI: Uri = FileProvider.getUriForFile(
this,
"com.kpa.android.fileprovider",
it
)
LogUtils.e(photoURI)
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO)
}
}
} catch (e: Exception) {
LogUtils.e("error ---> ${e.message}")
}
}
在Android 7.0以上路径是被私有化的,所以使用FileProvider
- 在onActivityResult 中通知相册同步到相册中
Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE).also { mediaScanIntent ->
val file = File(currentPhotoPath)
mediaScanIntent.data = Uri.fromFile(file)
LogUtils.e(mediaScanIntent.data)
sendBroadcast(mediaScanIntent)
}
- 在在onActivityResult中对图片进行尺寸压缩等进行使用
private fun setPic() {
val targetW: Int = cameraIv.width
val targetH: Int = cameraIv.height
val bmOptions = BitmapFactory.Options().apply {
inJustDecodeBounds = true
val photoW: Int = outWidth
val photoH: Int = outHeight
val scaleFactor: Int = Math.min(photoW / targetW, photoH / targetH)
inJustDecodeBounds = false
inSampleSize = scaleFactor
inPurgeable = true
}
BitmapFactory.decodeFile(currentPhotoPath, bmOptions)?.also { bitmap ->
cameraIv.setImageBitmap(bitmap)
}
}
二、录制视频
1.1 添加权限(同一中的权限申请)
1.2 调用相机
Intent(MediaStore.ACTION_VIDEO_CAPTURE).also { takeVideoIntent ->
takeVideoIntent.resolveActivity(packageManager)?.also {
startActivityForResult(takeVideoIntent, REQUEST_VIDEO_CAPTURE)
}
}
1.3 预览
使用VideoView 进行播放
override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
super.onActivityResult(requestCode, resultCode, intent)
if (requestCode == REQUEST_VIDEO_CAPTURE && resultCode == RESULT_OK) {
val videoUri: Uri? = intent?.data
videoVv.setVideoURI(videoUri)
videoVv.start()
}
}