Android视频采集渲染学习(1)
声明:代码来源于慕课网视频学习,跟随老师讲解手敲;如有侵权,请及时联系;
功能:Android kotlin基于cameraX,绑定摄像头到preview,imgcapture;进行拍照
注意拍照中的版本判断P,以及写权限,可能影响手机测试时候拍照报错:
qdgralloc: GetYUVPlaneInfo: Invalid format passed: 0x21
if(Build.VERSION.SDK_INT<Build.VERSION_CODES.P) { put(MediaStore.Images.Media.RELATIVE_PATH,"Pictures/CamX"); }
package com.example.cameraxdemo
import android.content.ContentValues
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
import android.util.Size
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.ScaleGestureDetector
import android.widget.Toast
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageCaptureException
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.video.OutputOptions
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.example.cameraxdemo.databinding.ActivityMainBinding
import java.lang.Exception
import java.text.SimpleDateFormat
import java.util.*
import java.util.jar.Manifest
import kotlin.math.log
class MainActivity : AppCompatActivity() {
private lateinit var viewBinding: ActivityMainBinding;
private var imgcap:ImageCapture?=null;
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewBinding =ActivityMainBinding.inflate(layoutInflater);
setContentView(viewBinding.root);
//权限判断
if(allpermissionagree())
{
//ok
Log.d("have static permission","permission ok");
startCamera();
}else{
ActivityCompat.requestPermissions(this, PermissList,permissCode);
}
viewBinding.imgCap.setOnClickListener({takephoto()});
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if(requestCode == permissCode)
{
if(allpermissionagree())
{
startCamera();
//ok
}else{
Log.d("no permission","onrequest permission result");
Toast.makeText(this, "no permission", Toast.LENGTH_SHORT).show();
finish();//程序结束
}
}
}
private fun allpermissionagree() = PermissList.all {
//遍历是否赋予了动态权限
ContextCompat.checkSelfPermission(baseContext,it)== PackageManager.PERMISSION_GRANTED;
}
private fun startCamera(){
//val 只赋值一次
val cameraProviderFuture = ProcessCameraProvider.getInstance(this);
//监听,主线程显示
cameraProviderFuture.addListener({
val cameraProvider:ProcessCameraProvider = cameraProviderFuture.get();
val preview =Preview.Builder().build().also { it.setSurfaceProvider(viewBinding.photoview.surfaceProvider) };
imgcap = ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
.setTargetResolution(Size(1920, 1080))
.build();
try {
cameraProvider.unbindAll();
//窗口绑定摄像头,后置摄像头
val camera = cameraProvider.bindToLifecycle(this, CameraSelector.DEFAULT_BACK_CAMERA,preview,imgcap);
val cameractonrol =camera.cameraControl;
val cameraInfo =camera.cameraInfo;
//cameractonrol.enableTorch(true);//允许拍照的时候开启闪光灯
//1手势监听
val gestureDetector = GestureDetector(this, object : GestureDetector.SimpleOnGestureListener() {
override fun onScroll(
e1: MotionEvent,
e2: MotionEvent,
distanceX: Float,
distanceY: Float
): Boolean {
val currentZoomRatio = cameraInfo.zoomState.value?.zoomRatio ?: 1f
val delta = (e1?.y ?: 0f) - (e2?.y ?: 0f)
val scale = delta / viewBinding.photoview.height.toFloat()
val zoomRatio = currentZoomRatio + scale
cameractonrol.setZoomRatio(
zoomRatio.coerceIn(
0f,
cameraInfo.zoomState.value?.maxZoomRatio ?: 1f
)
)
return true
}
})
viewBinding.photoview.setOnTouchListener { _, event ->
gestureDetector.onTouchEvent(event)
true
}
}catch (exec:Exception)
{
Log.e("preview bind fail","error");
}
},ContextCompat.getMainExecutor(this))
}
private fun takephoto()
{
Log.d("demo","test..........")
val imgCap =imgcap?:return;
val name = SimpleDateFormat( FORMATE, Locale.CHINA).format(System.currentTimeMillis())
//创建文件媒体信息保存contentresolve
val contentval =ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME,name);
put(MediaStore.MediaColumns.MIME_TYPE,"image/jpeg");
if(Build.VERSION.SDK_INT<Build.VERSION_CODES.P)
{
put(MediaStore.Images.Media.RELATIVE_PATH,"Pictures/CamX");
}
};
val outputOption =ImageCapture.OutputFileOptions.Builder(
contentResolver,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
contentval
).build();
imgCap.takePicture(outputOption,
ContextCompat.getMainExecutor(this),//主线程
object:ImageCapture.OnImageSavedCallback{
override fun onError(exception: ImageCaptureException) {
Log.e("take photo error","error");
}
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
Toast.makeText(baseContext, "take photo ok", Toast.LENGTH_SHORT).show()
}
}
)
}
//参数初始化
companion object{
private const val permissCode =10;
private val FORMATE ="yyyy-MM-dd-HH-mm-ss-SSS";
//权限列表
private val PermissList= mutableListOf(
android.Manifest.permission.CAMERA,
android.Manifest.permission.RECORD_AUDIO,
).apply {
if(Build.VERSION.SDK_INT <=Build.VERSION_CODES.P)
{
add(android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
}.toTypedArray();
}
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.camera.view.PreviewView
android:id="@+id/photoview"
android:layout_width ="match_parent"
android:layout_height ="match_parent"
tools:ignore="MissingConstraints" />
<Button
android:id="@+id/img_cap"
android:layout_width="150dp"
android:layout_height="60dp"
android:layout_margin="50dp"
android:text="take-photo"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.cameraxdemo">
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Cameraxdemo"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}
android {
compileSdk 33
defaultConfig {
applicationId "com.example.cameraxdemo"
minSdk 25
targetSdk 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures{
viewBinding true
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation "androidx.camera:camera-core:1.2.3"
implementation "androidx.camera:camera-camera2:1.2.3"
implementation "androidx.camera:camera-lifecycle:1.2.3"
implementation "androidx.camera:camera-video:1.2.3"
implementation "androidx.camera:camera-view:1.2.3"
implementation "androidx.camera:camera-extensions:1.2.3"
}
浙公网安备 33010602011771号