【问题标题】:Torch for camera "0" is not available due to an existing camera user由于现有相机用户,相机“0”的手电筒不可用
【发布时间】:2019-05-28 05:59:52
【问题描述】:

我想创建一个应用程序,该应用程序具有一个用于录制视频的按钮和另一个用于在录制视频期间打开闪光灯的单独切换按钮。

我已经使用 camera2 API 为最近的 androids 构建了相机应用程序,该应用程序由图像按钮访问。我将手电筒模式访问设置为切换按钮,但这根本不起作用。但是切换按钮可以单独访问闪光灯。

public class MainActivity extends AppCompatActivity {


    private TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() {
        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
            setupCamera(width,height);
            connectCamera();
        }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        createFolder();

        mMediaRecorder = new MediaRecorder();

        mTextureView = (TextureView) findViewById(R.id.textureView);
        mRecordButtonimg = (ImageButton) findViewById(R.id.video_online_button);
                mRecordButtonimg.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                if (misRecording) {
                    misRecording = false;
                    mRecordButtonimg.setImageResource(R.mipmap.ic_launcher);
                    mMediaRecorder.stop();
                    mMediaRecorder.reset();
                    startPreview();
                } else {
                    checkWriteStoragePermission();
                    misRecording = true;
                    mRecordButtonimg.setImageResource(R.mipmap.ic_launcher_round);
                }
            }
        });

        mButtonLights = (ToggleButton) findViewById(R.id.buttonLights);
        mButtonLights.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try{
                    cameraManager.setTorchMode(mCameraId, mButtonLights.isChecked());
                }catch (CameraAccessException e){
                    e.printStackTrace();
                }
            }
            });
    }
}

我刚刚将设置的手电筒模式添加到 onClickListener。我应该在其他地方添加它吗?因为它不会将其添加到预览中!而且我已经在代码中检查后置摄像头(手电筒的id是0),所以我不知道为什么代码不起作用。

【问题讨论】:

    标签: android android-camera2


    【解决方案1】:

    也许对你有帮助。我创建了一个将 OpenGL EL 着色器应用于相机预览的应用程序。我的任务几乎相同——在处理相机预览时通过按钮打开/关闭手电筒。 我设法很容易地做到了:我停止重复请求,打开/关闭构建器中的手电筒,然后开始重复请求。像这样的:

    cameraSession.stopRepeating()
    requestBuilder.set(CaptureRequest.FLASH_MODE, if(turnFlashOn) CaptureRequest.FLASH_MODE_TORCH else null)
    cameraSession.setRepeatingRequest(requestBuilder!!.build(), null, null)
    

    【讨论】:

    • 这里的cameraSessionrequestBuilder 是什么?
    【解决方案2】:

    弄清楚如何在相机预览时打开和关闭手电筒。 On 按钮单击以打开/关闭灯,使用此代码:

    //at some other function where camera is initialised and start preview
    //...
    Camera camera = Camera.open();
    camera.startPreview();
    //...
    boolean lightOn = false;
    //...
    
    buttonLight.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                    Camera.Parameters p = camera.getParameters();
    
                    if (!lightOn) {
                        lightOn = true;
                        p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                        camera.setParameters(p);
                    } else {
                        lightOn = false;
                        p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                        camera.setParameters(p);
                    }
            }
        });
    

    编码愉快! :D

    【讨论】:

    • @Psijic 你能解释一下已经打开的相机是什么意思吗?如果基于我上面的代码..第 3 行和第 4 行是打开相机的代码。已经打开的相机由 Camera 类型的变量“相机”持有。
    • 已经打开的相机意味着您没有存储相机变量,因为相机已被第 3 方打开。
    • @Psijic 在这种情况下,您可以查看这篇关于如何查找已打开的相机 stackoverflow.com/questions/21559699/… 的帖子,据我所知,如果不将相机 ID 存储在第一名...但是帖子中的一个答案显示了如何循环获取包含您想要的相机ID的相机信息,无论是正面还是背面等。
    【解决方案3】:

    使用下面的代码

    // write below line in Manifest file
     <uses-feature android:name="android.hardware.camera"
        android:required="true" />
    
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <permission android:name="android.permission.FLASHLIGHT"
        android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"
        android:protectionLevel="normal" />
    <uses-feature android:name="android.hardware.camera.flash" android:required="false" />
    
    
    // write below code in activity xml
     <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
    <LinearLayout
       android:orientation="horizontal"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
      <FrameLayout
          android:id="@+id/videoview"
          android:layout_width="500px"
          android:layout_height="480px"/>
      <LinearLayout
          android:orientation="vertical"
          android:layout_width="match_parent"
          android:layout_height="match_parent">
         <Button
             android:id="@+id/mybutton"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:text="REC"
             android:textSize="12dp"/>
         <RadioGroup
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:id="@+id/radio_group"
             android:orientation="vertical">
            <RadioButton
                android:id="@+id/flashoff"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="OFF"
                android:textSize="8dp"
                android:checked="true"/>
            <RadioButton
                android:id="@+id/flashtorch"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Torch"
                android:textSize="8dp"/>
         </RadioGroup>
        </LinearLayout>
       </LinearLayout>
      </LinearLayout>
    
    
     // Activity source code
    
     import android.Manifest;
     import android.content.Context;
     import android.content.pm.PackageManager;
     import android.hardware.Camera;
     import android.media.CamcorderProfile;
     import android.media.MediaRecorder;
     import android.os.Bundle;
     import android.support.annotation.NonNull;
     import android.support.v4.app.ActivityCompat;
     import android.support.v4.content.ContextCompat;
     import android.support.v7.app.AppCompatActivity;
     import android.util.Log;
     import android.view.MotionEvent;
      import android.view.SurfaceHolder;
     import android.view.SurfaceView;
     import android.view.View;
     import android.widget.Button;
     import android.widget.FrameLayout;
     import android.widget.RadioButton;
     import android.widget.Toast;
    
    import java.io.IOException;
    
    public class MainActivity extends AppCompatActivity {
    private Camera myCamera;
    private MyCameraSurfaceView myCameraSurfaceView;
    private MediaRecorder mediaRecorder;
    private Button myButton;
    private RadioButton flashOff, flashTorch;
    private SurfaceHolder surfaceHolder;
    boolean recording;
    private int PERMISSION_CODE=1021;
    private static final String LOG_TAG=MainActivity.class.getName();
    private String[] getDeviceIdPermissions = new String[]{
            Manifest.permission.CAMERA,
            android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
            android.Manifest.permission.READ_EXTERNAL_STORAGE,
            android.Manifest.permission.RECORD_AUDIO};
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if(!checkPermission()) {
            askPermission();
        }else{
            init();
        }
    }
    
    private boolean checkPermission() {
        if(isPermitted(getDeviceIdPermissions)){
            return true;
        }
        return false;
    }
    
    private void askPermission(){
        ActivityCompat.requestPermissions(this,getDeviceIdPermissions,PERMISSION_CODE);
    }
    
    Button.OnTouchListener flashButtonOnTouchListener
            = new Button.OnTouchListener(){
    
        @Override
        public boolean onTouch(View arg0, MotionEvent arg1) {
            // TODO Auto-generated method stub
    
            if(myCamera != null){
                Camera.Parameters parameters = myCamera.getParameters();
    
                switch (arg1.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                        myCamera.setParameters(parameters);
                        break;
                    case MotionEvent.ACTION_UP:
                        parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                        myCamera.setParameters(parameters);
                        break;
                };
            }
    
            return true;
        }};
    
    Button.OnClickListener flashModeButtonOnClickListener
            = new Button.OnClickListener(){
    
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
    
        }
    };
    
    Button.OnClickListener myButtonOnClickListener
            = new Button.OnClickListener(){
    
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            if(recording){
                // stop recording and release camera
                mediaRecorder.stop();  // stop the recording
                releaseMediaRecorder(); // release the MediaRecorder object
    
                //Exit after saved
                finish();
            }else{
    
                //Release Camera before MediaRecorder start
                releaseCamera();
    
                if(!prepareMediaRecorder()){
                    Toast.makeText(MainActivity.this,
                            "Fail in prepareMediaRecorder()!\n - Ended -",
                            Toast.LENGTH_LONG).show();
                    finish();
                }
    
                mediaRecorder.start();
                recording = true;
                myButton.setText("STOP");
            }
        }};
    
    private Camera getCameraInstance(){
        // TODO Auto-generated method stub
        Camera c = null;
        try {
            c = Camera.open(); // attempt to get a Camera instance
        }
        catch (Exception e){
            // Camera is not available (in use or does not exist)
        }
        return c; // returns null if camera is unavailable
    }
    
    
    private void init(){
        myCamera = getCameraInstance();
        if(myCamera == null){
            Log.d(LOG_TAG,"Failed to get camera");
        }
    
        myCameraSurfaceView = new MyCameraSurfaceView(this, myCamera);
        FrameLayout myCameraPreview = (FrameLayout)findViewById(R.id.videoview);
        myCameraPreview.addView(myCameraSurfaceView);
    
        myButton = (Button)findViewById(R.id.mybutton);
        myButton.setOnClickListener(myButtonOnClickListener);
    
        flashOff = (RadioButton)findViewById(R.id.flashoff);
        flashTorch = (RadioButton)findViewById(R.id.flashtorch);
    }
    
    private String getFlashModeSetting(){
        if(flashTorch.isChecked()){
            return Camera.Parameters.FLASH_MODE_TORCH;
        }else {
            return Camera.Parameters.FLASH_MODE_OFF;
        }
    }
    
    private boolean prepareMediaRecorder(){
        myCamera = getCameraInstance();
    
        Camera.Parameters parameters = myCamera.getParameters();
        parameters.setFlashMode(getFlashModeSetting());
        myCamera.setDisplayOrientation(90);
        myCamera.setParameters(parameters);
    
        mediaRecorder = new MediaRecorder();
    
        myCamera.unlock();
        mediaRecorder.setCamera(myCamera);
    
        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
    
        mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
    
        mediaRecorder.setOutputFile("/sdcard/myvideo.mp4");
        mediaRecorder.setMaxDuration(60000); // Set max duration 60 sec.
        mediaRecorder.setMaxFileSize(5000000); // Set max file size 5M
    
        mediaRecorder.setPreviewDisplay(myCameraSurfaceView.getHolder().getSurface());
    
        try {
            mediaRecorder.prepare();
        } catch (IllegalStateException e) {
            releaseMediaRecorder();
            return false;
        } catch (IOException e) {
            releaseMediaRecorder();
            return false;
        }
        return true;
    
    }
    
    @Override
    protected void onPause() {
        super.onPause();
        releaseMediaRecorder();       // if you are using MediaRecorder, release it first
        releaseCamera();              // release the camera immediately on pause event
    }
    
    private void releaseMediaRecorder(){
        if (mediaRecorder != null) {
            mediaRecorder.reset();   // clear recorder configuration
            mediaRecorder.release(); // release the recorder object
            mediaRecorder = null;
            myCamera.lock();           // lock camera for later use
        }
    }
    
    private void releaseCamera(){
        if (myCamera != null){
            myCamera.release();        // release the camera for other applications
            myCamera = null;
        }
    }
    
    public class MyCameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback{
    
        private SurfaceHolder mHolder;
        private Camera mCamera;
    
        public MyCameraSurfaceView(Context context, Camera camera) {
            super(context);
            mCamera = camera;
            mCamera.setDisplayOrientation(90);
            // Install a SurfaceHolder.Callback so we get notified when the
            // underlying surface is created and destroyed.
            mHolder = getHolder();
            mHolder.addCallback(this);
            // deprecated setting, but required on Android versions prior to 3.0
            mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        }
    
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int weight,
                                   int height) {
            // If your preview can change or rotate, take care of those events here.
            // Make sure to stop the preview before resizing or reformatting it.
    
            if (mHolder.getSurface() == null){
                // preview surface does not exist
                return;
            }
    
            // stop preview before making changes
            try {
                mCamera.stopPreview();
            } catch (Exception e){
                // ignore: tried to stop a non-existent preview
            }
    
            // make any resize, rotate or reformatting changes here
    
            // start preview with new settings
            try {
                mCamera.setPreviewDisplay(mHolder);
                mCamera.startPreview();
    
            } catch (Exception e){
            }
        }
    
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            // TODO Auto-generated method stub
            // The Surface has been created, now tell the camera where to draw the preview.
            try {
                mCamera.setPreviewDisplay(holder);
                mCamera.startPreview();
            } catch (IOException e) {
            }
        }
    
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            // TODO Auto-generated method stub
    
        }
    }
    
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        boolean isPermitted =isPermitted(permissions);
        if(isPermitted){
            if(requestCode==PERMISSION_CODE){
                init();
            }
        }
    }
    
    public boolean isPermitted(String[] permissions) {
        boolean havePermission;
        for (String permission : permissions) {
            havePermission = (ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED);
            if (!havePermission)
                return false;
        }
        return true;
    }
    }
    

    【讨论】:

    • 嘿,我使用的是 camera2API,而不是旧版本,所以你能给我一个想法,让我在录制视频时设置我的闪光灯。
    【解决方案4】:

    也许它有帮助,我的任务几乎相同 - 在处理相机预览时通过按钮打开/关闭手电筒。我停止使用会话重复请求,创建新的捕获请求对象,在构建器中打开/关闭手电筒,然后开始重复请求。

    注意:如果您使用相机 api 2,此解决方案对您来说是救命稻草。

    类似这样的:

    private fun enableFlash() {
    
            //isTorchON = true
            session.stopRepeating()
    
            //camera is a DeviceCamera object
            //fragmentCameraBinding.viewFinder is a AutoSurfaceView
            //session is a CameraCaptureSession
    
            val captureRequest = camera.createCaptureRequest(
                CameraDevice.TEMPLATE_PREVIEW).apply { addTarget(fragmentCameraBinding.viewFinder.holder.surface) }
    
            captureRequest.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH)
    
            session.setRepeatingRequest(captureRequest.build(), null, cameraHandler)
        }
    
        private fun disableFlash() {
            //isTorchON = false
    
            session.stopRepeating()
    
            val captureRequest = camera.createCaptureRequest(
                CameraDevice.TEMPLATE_PREVIEW).apply { addTarget(fragmentCameraBinding.viewFinder.holder.surface) }
    
            session.setRepeatingRequest(captureRequest.build(), null, cameraHandler)
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-23
      • 1970-01-01
      • 1970-01-01
      • 2017-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多