Samsung Galaxy A3 (2014) で SDK v21 をテストし、Nexus 5X で v23 をテストします。Camera2Basic の例もテストしましたが、両方のデバイスで動作します。私の小さなコードの再構築 (フラグメントの代わりにアクティビティを使用) が、両方のデバイスの一方のみでこのエラーを引き起こすのはなぜだろうか。
// ...
protected void onCreate() {
// setContentView ...
viewfinder = (AutoFitTextureView)findViewById(R.id.viewfinder);
// Choose back camera device, choose maxPictureSize (for JPEG), find out whether dimensions must be swapped
if (!swappedDimensions)
viewfinder.setAspectRatio(maxPictureSize.getWidth(), maxPictureSize.getHeight());
else
viewfinder.setAspectRatio(maxPictureSize.getHeight(), maxPictureSize.getWidth());
// initialize image reader
}
protected void onResume() {
if (viewfinder.isAvailable()) {
// Alternative to call in onSurfaceTextureAvailable()
init();
}
else {
viewfinder.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {
Log.d(tag(), "surfaceTexture available: " + width + " x " + height);
configureSurface(width, height);
init();
}
public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) {
Log.d(tag(), "surfaceTexture size changed: " + width + " x " + height);
// Currently, don't react to changes. In opposite to the surface change listener, this method is not called after onSurfaceTextureAvailable and only needs to be implemented if the texture view size will change during the app is running
}
public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) {
Log.d(tag(), "surfaceTexture destroyed");
return true;
}
public void onSurfaceTextureUpdated(SurfaceTexture texture) {
Log.d(tag(), "surfaceTexture updated");
}
});
}
try {
if (!openCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
throw new RuntimeException("Time out waiting to lock camera opening.");
}
cameraManager.openCamera(deviceId, new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice camera) {
openCloseLock.release();
device = camera;
init();
}
// ...
}, null);
}
catch(InterruptedException e) {
// ...
}
}
protected void configureSurface(int view_width, int view_height) {
SurfaceTexture surfaceTexture = viewfinder.getSurfaceTexture();
if (surfaceTexture == null)
return;
// Can this be changed after the session has been started?:
Size rotatedSurfaceSize = swappedDimensions
? new Size(view_height, view_width)
: new Size(view_width, view_height);
Size previewSize = bestOutputSize(SurfaceTexture.class, rotatedSurfaceSize, Sizes.aspectRatio(maxPictureSize));
Log.i(tag(), "Preview size for " + rotatedSurfaceSize + " (" + Sizes.aspectRatio(maxPictureSize) + ":1): "+previewSize);
surfaceTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
//
// Copied from Camera2Basic, just changed var names:
int rotation = getWindowManager().getDefaultDisplay().getRotation();
Matrix matrix = new Matrix();
RectF viewRect = new RectF(0, 0, view_width, view_height);
RectF bufferRect = new RectF(0, 0, previewSize.getHeight(), previewSize.getWidth());
float centerX = viewRect.centerX();
float centerY = viewRect.centerY();
if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
float scale = Math.max(
(float) view_height / previewSize.getHeight(),
(float) view_width / previewSize.getWidth());
matrix.postScale(scale, scale, centerX, centerY);
matrix.postRotate(90 * (rotation - 2), centerX, centerY);
} else if (Surface.ROTATION_180 == rotation) {
matrix.postRotate(180, centerX, centerY);
}
viewfinder.setTransform(matrix);
//
}
/**
* Prerequisites:
* - The device must be opened.
* - The surface texture must be available.
*/
protected void init() {
// Executed only after second call, loadingState makes sure both prerequisites are true
if (++loadingState != 2)
return;
final CameraDevice d = device;
final Surface surface = new Surface(viewfinder.getSurfaceTexture());
try {
previewRequestBuilder = d.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
previewRequestBuilder.addTarget(surface);
} catch (CameraAccessException e) {
e.printStackTrace();
}
CameraCaptureSession.StateCallback cb = new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(CameraCaptureSession cameraCaptureSession) {
// The camera is already closed
if (d == null) {
return;
}
Log.d(tag(), "Configured!");
// When the session is ready, we start displaying the preview.
captureSession = cameraCaptureSession;
try {
Log.d(tag(), "Surface: " + surface);
previewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_OFF);
previewRequest = previewRequestBuilder.build();
captureSession.setRepeatingRequest(previewRequest, previewCallback, null);
Log.d(tag(), "Preview started!");
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
Log.e(tag(), "Configure failed!");
}
};
try {
d.createCaptureSession(Arrays.asList(surface, imageReader.getSurface()), cb, null);
Log.d(tag(), "Session started");
}
catch (CameraAccessException e) {
}
}
// ...
私自身のログ出力は、エラーや例外がスローされることなく、両方のデバイスで同じであり、両方ともCameraCaptureSession.CaptureCallback.onCaptureCompleted
定期TextureView.SurfaceTextureListener.onSurfaceTextureUpdated
的に呼び出されます。(おそらく、別のストーリーを伝えるカメラ サービスからのエントリがありますが、これらのエラーは、アクティビティでスローされた明示的なエラーに反映されるはずです。) プレビューは、私の Samsung デバイスでのみライブであり、Nexus では適切なサイズですが、黒のままです。