我目前正在为我的平板电脑(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);
再次感谢