偶尔在服务中运行Android的Camera2API .setRepeatingRequest()的CameraAccessException / IllegalStateException

时间:2019-01-27 02:41:41

标签: java android android-service android-camera2

我目前正在为我的平板电脑(Android 7.0)开发一个智能镜像应用程序,该应用程序涉及一项服务,该服务不断拍摄照片而不会显示.setRepeatingRequest。此服务将所有图像保存在同一位置/image.jpg,以便image.jpg不断更新(约3fps)。有时,应用程序崩溃了,我不知道为什么。 这是典型的流程流: 应用程序开始->主要活动(显示一些有关天气的数据。)->几秒钟后,处理程序启动第二个活动(通过调用startActivity(intent))->此第二个活动使用以下命令启动服务

startService(new Intent(this, Camera2Service.class));

->现在每隔一秒钟,该应用程序就会检查当前图像上是否有可见的面孔,如果存在,则在短暂的延迟后再次启动startActivity(intent),返回主窗口,并启动新的cicle。

这在大多数情况下都可以正常工作,即许多小柱没有任何错误。一旦在其中一张图像上识别出脸部,该应用程序就会从显示主要活动的数据来回切换到“黑屏-睡眠模式”第二活动,然后再来回切换。现在,有时在一个周期之后,有时甚至在十个周期之后,secondActicity似乎崩溃了,或者至少该应用没有通常的问候语就切换回了main,而logcat中出现以下错误:

java.lang.IllegalStateException: Session has been closed; further changes are illegal.
    at android.hardware.camera2.impl.CameraCaptureSessionImpl.checkNotClosed(CameraCaptureSessionImpl.java:607)
    at android.hardware.camera2.impl.CameraCaptureSessionImpl.setRepeatingRequest(CameraCaptureSessionImpl.java:227)

此后,mainActivity像往常一样递减计数,直到尝试切换到secondActivity。然后,secondActivity尝试再次启动该服务时,该应用程序最终会因以下原因而完全崩溃:

2019-01-27 03:05:19.166 22434-22434/com.krautkremer.nils.mymirror E/BufferItemConsumer: [ImageReader-640x480f100m2-22434-0] Failed to release buffer: Unknown error -1 (1)
2019-01-27 03:05:19.166 22434-22434/com.krautkremer.nils.mymirror E/BufferItemConsumer: [ImageReader-640x480f100m2-22434-0] Failed to release buffer: Unknown error -1 (1)
2019-01-27 03:05:19.166 22434-22434/com.krautkremer.nils.mymirror E/BufferItemConsumer: [ImageReader-640x480f100m2-22434-0] Failed to release buffer: Unknown error -1 (1)
2019-01-27 03:05:19.176 22434-22434/com.krautkremer.nils.mymirror E/BufferItemConsumer: [ImageReader-640x480f100m2-22434-0] Failed to release buffer: Unknown error -1 (1)
2019-01-27 03:05:19.178 22434-22434/com.krautkremer.nils.mymirror E/CameraCaptureSession: Session 0: Exception while stopping repeating: 
android.hardware.camera2.CameraAccessException: CAMERA_DISCONNECTED (2): checkPidStatus:1096: The camera device has been disconnected
    at android.hardware.camera2.CameraManager.throwAsPublicException(CameraManager.java:633)
    at android.hardware.camera2.impl.ICameraDeviceUserWrapper.cancelRequest(ICameraDeviceUserWrapper.java:95)
    at android.hardware.camera2.impl.CameraDeviceImpl.stopRepeating(CameraDeviceImpl.java:926)
    at android.hardware.camera2.impl.CameraCaptureSessionImpl.close(CameraCaptureSessionImpl.java:379)
    at android.hardware.camera2.impl.CameraCaptureSessionImpl$2.onDisconnected(CameraCaptureSessionImpl.java:515)
    at android.hardware.camera2.impl.CameraDeviceImpl$7.run(CameraDeviceImpl.java:228)
    at android.os.Handler.handleCallback(Handler.java:761)
    at android.os.Handler.dispatchMessage(Handler.java:98)
    at android.os.Looper.loop(Looper.java:156)
    at android.app.ActivityThread.main(ActivityThread.java:6623)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)
 Caused by: android.os.ServiceSpecificException: checkPidStatus:1096: The camera device has been disconnected
    at android.os.Parcel.readException(Parcel.java:1679)
    at android.os.Parcel.readException(Parcel.java:1618)
    at android.hardware.camera2.ICameraDeviceUser$Stub$Proxy.cancelRequest(ICameraDeviceUser.java:350)
    at android.hardware.camera2.impl.ICameraDeviceUserWrapper.cancelRequest(ICameraDeviceUserWrapper.java:93)
    at android.hardware.camera2.impl.CameraDeviceImpl.stopRepeating(CameraDeviceImpl.java:926) 
    at android.hardware.camera2.impl.CameraCaptureSessionImpl.close(CameraCaptureSessionImpl.java:379) 
    at android.hardware.camera2.impl.CameraCaptureSessionImpl$2.onDisconnected(CameraCaptureSessionImpl.java:515) 
    at android.hardware.camera2.impl.CameraDeviceImpl$7.run(CameraDeviceImpl.java:228) 
    at android.os.Handler.handleCallback(Handler.java:761) 
    at android.os.Handler.dispatchMessage(Handler.java:98) 
    at android.os.Looper.loop(Looper.java:156) 
    at android.app.ActivityThread.main(ActivityThread.java:6623) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832) 
2019-01-27 03:05:19.183 22434-22434/com.krautkremer.nils.mymirror E/CameraCaptureSession: Session 0: Failed to create capture session; configuration failed
2019-01-27 03:05:19.183 22434-22434/com.krautkremer.nils.mymirror E/logging: CAMERA_DISCONNECTED (2): checkPidStatus:1096: The camera device has been disconnected
2019-01-27 03:05:19.186 26720-26720/? E/FullInputEventModel: onStartInput event aborted: eeg: could not obtain extracted text (class eeg)
2019-01-27 03:05:19.187 431-2732/? E/ANDR-PERF-MPCTL: invalid request, no optimizations performed
2019-01-27 03:05:19.187 22783-22783/? E/QCamera: <MCI><ERROR> mm_channel_fsm_fn_stopped: 918: invalid state (1) for evt (6)
2019-01-27 03:05:19.235 22783-22783/? E/mm-still: virtual OMX_ERRORTYPE QOMXImageCodec::omx_component_set_callbacks(OMX_HANDLETYPE, OMX_CALLBACKTYPE *, OMX_PTR): Bad Parameter
2019-01-27 03:05:19.236 22783-22783/? E/QCamera: <HAL><ERROR> int32_t qcamera::QCameraPerfLock::lock_rel(): 448: failed to release lock
2019-01-27 03:05:19.262 22783-22889/? E/Camera2-Metadata: Mismatched tag type when updating entry enable (-2146959360) of type byte; got type int32 data instead 
2019-01-27 03:05:19.262 22783-22889/? E/Camera2-Metadata: Mismatched tag type when updating entry is_main (-2146959359) of type byte; got type int32 data instead 
2019-01-27 03:05:19.264 22434-22434/com.krautkremer.nils.mymirror E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.krautkremer.nils.mymirror, PID: 22434
java.lang.IllegalStateException: Session has been closed; further changes are illegal.
    at android.hardware.camera2.impl.CameraCaptureSessionImpl.checkNotClosed(CameraCaptureSessionImpl.java:607)
    at android.hardware.camera2.impl.CameraCaptureSessionImpl.setRepeatingRequest(CameraCaptureSessionImpl.java:227)
    at com.krautkremer.nils.mymirror.Camera2Service$2.onReady(Camera2Service.java:80)
    at java.lang.reflect.Method.invoke(Native Method)
    at android.hardware.camera2.dispatch.InvokeDispatcher.dispatch(InvokeDispatcher.java:39)
    at android.hardware.camera2.dispatch.HandlerDispatcher$1.run(HandlerDispatcher.java:65)
    at android.os.Handler.handleCallback(Handler.java:761)
    at android.os.Handler.dispatchMessage(Handler.java:98)
    at android.os.Looper.loop(Looper.java:156)
    at android.app.ActivityThread.main(ActivityThread.java:6623)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)

因此,我相信,由于服务和repeatingRequest之前未正确关闭,导致了最终崩溃。我的问题是,为什么有时我会首先获得这些奇怪的IllegalStateExceptions来阻止secondActivity终止服务。 我知道有一些SO问题涉及类似的错误,但我发现这些问题都不适合这种特殊情况(repeatingRequest,Service)。 感谢您的帮助,我对Android和Java还是很陌生,而这个camera2api令我非常困惑。这些是我代码的相关部分,请询问您是否还需要其他任何内容:

服务类别:

public class Camera2Service extends Service
{

protected static final String TAG = "logging";
protected static final int CAMERACHOICE = CameraCharacteristics.LENS_FACING_BACK;
protected CameraDevice cameraDevice;
protected CameraCaptureSession session;
protected ImageReader imageReader;
private Handler mHandler = new Handler();

 protected CameraDevice.StateCallback cameraStateCallback = new CameraDevice.StateCallback() {
    @Override
    public void onOpened(@NonNull CameraDevice camera) {
        Log.i(TAG, "CameraDevice.StateCallback onOpened");
        cameraDevice = camera;
        actOnReadyCameraDevice();
    }

    @Override
    public void onDisconnected(@NonNull CameraDevice camera) {
        Log.i(TAG, "CameraDevice.StateCallback onDisconnected");
    }

    @Override
    public void onError(@NonNull CameraDevice camera, int error) {
        Log.i(TAG, "CameraDevice.StateCallback onError " + error);
    }
};

protected CameraCaptureSession.StateCallback sessionStateCallback = new CameraCaptureSession.StateCallback() {

    @Override
    public void onReady(CameraCaptureSession session) {
        Camera2Service.this.session = session;
        try {
            session.setRepeatingRequest(createCaptureRequest(), null, null);
        } catch (CameraAccessException e) {
            Log.e(TAG, e.getMessage());
        }
    }


    @Override
    public void onConfigured(CameraCaptureSession session) {

    }

    @Override
    public void onConfigureFailed(@NonNull CameraCaptureSession session) {
    }
};

protected ImageReader.OnImageAvailableListener onImageAvailableListener = new ImageReader.OnImageAvailableListener() {
    @Override
    public void onImageAvailable(ImageReader reader) {
        Log.i(TAG, "onImageAvailable");
        Image img = reader.acquireLatestImage();
        if (img != null) {
            processImage(img);
            img.close();
        }
    }
};


public void readyCamera() {
    Log.i(TAG, "so far 1");
    CameraManager manager = (CameraManager) getSystemService(CAMERA_SERVICE);
    Log.i(TAG, "so far 2 ");
    try {
        String pickedCamera = getCamera(manager);
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        manager.openCamera(pickedCamera, cameraStateCallback, null);
        imageReader = ImageReader.newInstance(640, 480, ImageFormat.JPEG, 2 /* images buffered */);
        imageReader.setOnImageAvailableListener(onImageAvailableListener, null);
        Log.i(TAG, "imageReader created");
    } catch (CameraAccessException e){
        Log.i(TAG, e.getMessage());
    }
}

public String getCamera(CameraManager manager){
    try {
        for (String cameraId : manager.getCameraIdList()) {
            CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
            int cOrientation = characteristics.get(CameraCharacteristics.LENS_FACING);
            Log.i(TAG, "cameraid: " + cameraId);
            if (cOrientation != CAMERACHOICE) {
                return cameraId;
            }
        }
    } catch (CameraAccessException e){
        e.printStackTrace();
    }
    return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.i(TAG, "onStartCommand flags " + flags + " startId " + startId);
    Log.i(TAG,"onStart service");
    readyCamera();

    return super.onStartCommand(intent, flags, startId);
}



@Override
public void onCreate() {
    Log.i(TAG,"onCreate service");
    super.onCreate();
}

public void actOnReadyCameraDevice()
{
    try {
        cameraDevice.createCaptureSession(Arrays.asList(imageReader.getSurface()), sessionStateCallback, null);
    } catch (CameraAccessException e){
        Log.e(TAG, e.getMessage());
    }
}

@Override
public void onDestroy() {
    try {
        session.stopRepeating();
        session.abortCaptures();
    } catch (CameraAccessException e){
        Log.e(TAG, e.getMessage());
    }
    session.close();
}


private void processImage(Image image){
    //Process image data
    ByteBuffer buffer;
    byte[] bytes;
    boolean success = false;
    File file = new File(Environment.getExternalStorageDirectory() + "/Pictures/image.jpg");
    FileOutputStream output = null;

    if(image.getFormat() == ImageFormat.JPEG) {
        buffer = image.getPlanes()[0].getBuffer();
        bytes = new byte[buffer.remaining()]; // makes byte array large enough to hold image
        buffer.get(bytes); // copies image from buffer to byte array
        try {
            output = new FileOutputStream(file);
            output.write(bytes);    // write the byte array to file
            //j++;
            success = true;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            image.close(); // close this to free up buffer for other images
            if (null != output) {
                try {
                    output.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }


}

protected CaptureRequest createCaptureRequest() {
    try {
        CaptureRequest.Builder builder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
        builder.addTarget(imageReader.getSurface());
        builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
        builder.set(CaptureRequest.CONTROL_AE_LOCK, true);
        builder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 1);
        return builder.build();
    } catch (CameraAccessException e) {
        Log.e(TAG, e.getMessage());
        return null;
    }
}



@Override
public IBinder onBind(Intent intent) {
    return null;
}

secondActivity onPause()和onResume():

 @Override
protected void onPause(){
    super.onPause();
    stopService(new Intent(this, Camera2Service.class));


}
@Override
protected void onResume(){
    super.onResume();
    startService(new Intent(this, Camera2Service.class));


}

这就是我回到主站的方式:

mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
            try {
                Intent intent = new Intent(sleepingtime.this, MainActivity.class);
                startActivity(intent);
            } catch(Exception e){
                e.printStackTrace();
                Log.i(TAG, "Error calling activity MainActivity " + e);
            }
        }
    }, countdownms);

再次感谢

0 个答案:

没有答案