我想同时使用视频视图和相机预览

问题描述 投票:0回答:1

我目前正在开发一个基本的应用程序,该应用程序使用Android集成摄像头和Camera X来录制视频,尽管我正在努力,但我想同时在视频视图中查看完全不相关的视频同一个屏幕。

我认为问题可能出在 videoview 本身上,而且事实上它在同时使用时与录音机的播放效果不佳,所以我尝试了 webview

发生的情况是,视频视图或网络视图获得焦点并在没有预览的情况下运行视频,反之亦然 我尝试过使用链接到 youtube 的 Videoview 和 Webview,但仍然没有骰子 是否可以在使用相机/网络视图的同时观看视频?

Here is my XML:

    <?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=".Kamera">


    <androidx.camera.view.PreviewView
        android:id="@+id/viewFinder"
        android:layout_width="411dp"
        android:layout_height="162dp"
        app:layout_constraintBottom_toBottomOf="parent"
        tools:layout_editor_absoluteX="0dp" />
    <Button
        android:id="@+id/exit_to_main"
        android:layout_width="107dp"
        android:layout_height="57dp"
        android:elevation="2dp"
        android:text="@string/exit"
        tools:layout_editor_absoluteX="149dp"
        tools:layout_editor_absoluteY="624dp" />


    <Button
        android:id="@+id/image_capture_button"
        android:layout_width="132dp"
        android:layout_height="58dp"
        android:elevation="2dp"
        android:text="@string/take_photo"
        tools:layout_editor_absoluteX="24dp"
        tools:layout_editor_absoluteY="624dp" />


    <Button
        android:id="@+id/video_capture_button"
        android:layout_width="132dp"
        android:layout_height="58dp"
        android:elevation="2dp"
        android:text="@string/start_capture"
        tools:layout_editor_absoluteX="256dp"
        tools:layout_editor_absoluteY="624dp" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/vertical_centerline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.5" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/horizontal_centerline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.0" />

    <WebView
        android:id="@+id/Webview"
        android:layout_width="411dp"
        android:layout_height="478dp"
        android:layout_marginStart="1dp"
        android:layout_marginEnd="1dp"
        android:layout_marginBottom="1dp"
        app:layout_constraintBottom_toTopOf="@+id/viewFinder"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="1.0" />


   </androidx.constraintlayout.widget.ConstraintLayout>

Here is my Kotlin code
    
    ```
    
    import android.Manifest
    import android.annotation.SuppressLint
    import android.content.ContentValues
    import android.content.pm.PackageManager
    import android.os.Build
    import android.os.Bundle
    import android.provider.MediaStore
    import android.util.Log
    import android.widget.Toast
    import androidx.activity.result.contract.ActivityResultContracts
    import androidx.appcompat.app.AppCompatActivity
    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.MediaStoreOutputOptions
    import androidx.camera.video.Recorder
    import androidx.camera.video.Recording
    import androidx.camera.video.VideoCapture
    import androidx.camera.video.VideoRecordEvent
    import androidx.core.content.ContextCompat
    import androidx.core.content.PermissionChecker
    import com.dabs.kitchenkaraoke.databinding.ActivityMainBinding
    import java.text.SimpleDateFormat
    import java.util.Locale
    import java.util.concurrent.ExecutorService
    import java.util.concurrent.Executors
    
    class Kamera : AppCompatActivity() {
    
        private lateinit var viewBinding: ActivityMainBinding
    
        private var imageCapture: ImageCapture? = null
    
        private var videoCapture: VideoCapture<Recorder>? = null
        private var recording: Recording? = null
    
        private lateinit var cameraExecutor: ExecutorService
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            viewBinding = ActivityMainBinding.inflate(layoutInflater)
            setContentView(viewBinding.root)
    
            // Request camera permissions
            if (allPermissionsGranted()) {
                startCamera()
            } else {
                requestPermissions()
            }
    
            // Set up the listeners for take photo and video capture buttons
            viewBinding.imageCaptureButton.setOnClickListener { takePhoto() }
            viewBinding.videoCaptureButton.setOnClickListener { captureVideo() }
            viewBinding.exitToMain?.setOnClickListener { finish() }
            cameraExecutor = Executors.newSingleThreadExecutor()
        }
    
        private fun takePhoto() {
            // Get a stable reference of the modifiable image capture use case
            val imageCapture = imageCapture ?: return
    
            // Create time stamped name and MediaStore entry.
            val name = SimpleDateFormat(FILENAME_FORMAT, Locale.UK)
                .format(System.currentTimeMillis())
            val contentValues = 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/CameraX-Image")
                }
            }
    
            // Create output options object which contains file + metadata
            val outputOptions = ImageCapture.OutputFileOptions
                .Builder(
                    contentResolver,
                    MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    contentValues
                )
                .build()
    
            // Set up image capture listener, which is triggered after photo has
            // been taken
            imageCapture.takePicture(
                outputOptions,
                ContextCompat.getMainExecutor(this),
                object : ImageCapture.OnImageSavedCallback {
                    override fun onError(exc: ImageCaptureException) {
                        Log.e(TAG, "Photo capture failed: ${exc.message}", exc)
                    }
    
                    override fun
                            onImageSaved(output: ImageCapture.OutputFileResults) {
                        val msg = "Photo capture succeeded: ${output.savedUri}"
                        Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
                        Log.d(TAG, msg)
                    }
                }
            )
        }
    
    
        private fun captureVideo() {
            val videoCapture = this.videoCapture ?: return
    
            viewBinding.videoCaptureButton.isEnabled = true
    
            val curRecording = recording
            if (curRecording != null) {
                // Stop the current recording session.
                curRecording.stop()
                recording = null
                return
            }
    
            // create and start a new recording session
            val name = SimpleDateFormat(FILENAME_FORMAT, Locale.UK)
                .format(System.currentTimeMillis())
            val contentValues = ContentValues().apply {
                put(MediaStore.MediaColumns.DISPLAY_NAME, name)
                put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4")
                if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
                    put(MediaStore.Video.Media.RELATIVE_PATH, "Movies/CameraX-Video")
                }
            }
    
            val mediaStoreOutputOptions = MediaStoreOutputOptions
                .Builder(contentResolver, MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
                .setContentValues(contentValues)
                .build()
            recording = videoCapture.output
                .prepareRecording(this, mediaStoreOutputOptions)
                .apply {
                    if (PermissionChecker.checkSelfPermission(
                            this@Kamera,
                            Manifest.permission.RECORD_AUDIO
                        ) ==
                        PermissionChecker.PERMISSION_GRANTED
                    ) {
                        withAudioEnabled()
                    }
                }
                .start(ContextCompat.getMainExecutor(this)) { recordEvent ->
                    when (recordEvent) {
                        is VideoRecordEvent.Start -> {
                            viewBinding.videoCaptureButton.apply {
                                text = getString(R.string.stop_capture)
                                isEnabled = true
                            }
                        }
    
                        is VideoRecordEvent.Finalize -> {
                            if (!recordEvent.hasError()) {
                                val msg = "Video capture succeeded: " +
                                        "${recordEvent.outputResults.outputUri}"
                                Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT)
                                    .show()
                                Log.d(TAG, msg)
                            } else {
                                recording?.close()
                                recording = null
                                Log.e(
                                    TAG, "Video capture ends with error: " +
                                            "${recordEvent.error}"
                                )
                            }
                            viewBinding.videoCaptureButton.apply {
                                text = getString(R.string.start_capture)
                                isEnabled = true
                            }
                        }
                    }
                }
        }
    
    
        @SuppressLint("RestrictedApi")
        private fun startCamera() {
            val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
    
            cameraProviderFuture.addListener({
                // Used to bind the lifecycle of cameras to the lifecycle owner
                val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
    
                // Preview
                val preview = Preview.Builder()
                    .build()
                    .also {
                        it.setSurfaceProvider(viewBinding.viewFinder.surfaceProvider)
                        imageCapture = ImageCapture.Builder().build()
                    }
    
                // Select back camera as a default
                val cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA
    
                try {
                    // Unbind use cases before rebinding
                    cameraProvider.unbindAll()
    
                    // Bind use cases to camera
                    cameraProvider.bindToLifecycle(
                        this, cameraSelector, preview, imageCapture, videoCapture)
    
                } catch(exc: Exception) {
                    Log.e(TAG, "Use case binding failed", exc)
                }
    
            }, ContextCompat.getMainExecutor(this))
        }
    
    
        private fun requestPermissions() {
            activityResultLauncher.launch(REQUIRED_PERMISSIONS)
        }
    
        private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
            ContextCompat.checkSelfPermission(
                baseContext, it
            ) == PackageManager.PERMISSION_GRANTED
        }
    
        override fun onDestroy() {
            super.onDestroy()
            cameraExecutor.shutdown()
        }
    
        companion object {
            private const val TAG = "CameraXApp"
            private const val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS"
            private val REQUIRED_PERMISSIONS =
                mutableListOf(
                    Manifest.permission.CAMERA,
                    Manifest.permission.RECORD_AUDIO
                ).apply {
                    if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
                        add(Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    }
                }.toTypedArray()
        }
    
        private val activityResultLauncher =
            registerForActivityResult(
                ActivityResultContracts.RequestMultiplePermissions()
            )
            { permissions ->
    
                // Handle Permission granted/rejected
                var permissionGranted = true
                permissions.entries.forEach {
                    if (it.key in REQUIRED_PERMISSIONS && it.value == false)
                        permissionGranted = false
                }
                if (!permissionGranted) {
                    Toast.makeText(
                        baseContext,
                        "Permission request denied",
                        Toast.LENGTH_SHORT
                    ).show()
                } else {
                    startCamera()
                }
                if (!permissionGranted) {
                    Toast.makeText(
                        baseContext,
                        "Permission request denied",
                        Toast.LENGTH_SHORT
                    ).show()
    
                }
                else {
                    startCamera()
    
                }
    
    
            }
    
    
            class Kamera : Activity() {
                private var wv1: WebView? = null
                val url = "https://www.youtube.com"
    
    
                override fun onCreate(savedInstanceState: Bundle?) {
                    super.onCreate(savedInstanceState)
                    setContentView(R.layout.activity_main)
    
                    wv1 = findViewById<android.view.View>(R.id.Webview) as WebView
                    wv1!!.webViewClient = MyBrowser()
    
                    //    val url = ed1!!.text.toString()
                    // Suppress scripting attacks
                    wv1!!.settings.loadsImagesAutomatically = true
                    wv1!!.settings.javaScriptEnabled = true
                    wv1!!.scrollBarStyle = android.view.View.SCROLLBARS_INSIDE_OVERLAY
                    wv1!!.settings.javaScriptEnabled = true
                    wv1!!.settings.saveFormData = true
                    wv1!!.loadUrl(url)
                }
    
                private inner class MyBrowser : WebViewClient() {
                    override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
                        view.loadUrl(url)
                        wv1!!.reload()
                        return true
                    }
                }
            }
        }
    
    
    ```
android-videoview android-camerax
1个回答
0
投票

问题似乎出在视图绑定上。经过一番深入研究,视频似乎没有正确初始化

  private lateinit var viewBinding: ActivityMainBinding
    private lateinit var frameL : FrameLayout
    private lateinit var video : VideoView
    private var imageCapture: ImageCapture? = null

    private var videoCapture: VideoCapture<Recorder>? = null
    private var recording: Recording? = null

    private lateinit var cameraExecutor: ExecutorService


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        viewBinding = ActivityMainBinding.inflate(layoutInflater)

        setContentView(viewBinding.root)
        viewBinding.videoView.setVideoURI(Uri.parse("https://law.duke.edu/cspd/contest/videos/Framed-Contest_Documentaries-and-You.mp4"))
        viewBinding.videoView.start()
© www.soinside.com 2019 - 2024. All rights reserved.