Tôi hy vọng các LogCat được đăng #onPreviewFrame()
nhiều lần, nhưng nó chỉ hoạt động trên các thiết bị được lựa chọn như:Máy ảnh onPreviewFrame không kêu gọi một số thiết bị
- Samsung Galaxy S6 (7.0)
- Samsung Galaxy S6 (6.0.1)
- LG Leon (5.0.1)
Nhưng không trên các thiết bị sau:
- LG G4 (6.0)
- Huawei 6X (7.0)
- Nexus 6P (7,0)
Dưới đây là đoạn mã:
public CameraSurfaceView(Context context, AttributeSet set) {
super(context, set);
Log.d(TAG, "CameraSurfaceView(context, set)");
// Get the Surface Holder
this.holder = this.getHolder();
this.holder.addCallback(this);
this.holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
// Turn on the Camera
this.camera = Camera.open();
} catch (Exception ex) {
Log.e(TAG, "#surfaceCreated() error=" + ex.getMessage(), ex);
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.d(TAG, "#surfaceChanged()");
if (holder.getSurface() == null) {
// preview surface does not exist
return;
}
if (camera == null) {
// camera does not exist
return;
}
// This allows us to make our own draw calls to this canvas
this.setWillNotDraw(false);
// Initialize canvas variables
previewPaint = new Paint();
// Initialize preview variables
deviceWidth = width;
deviceHeight = height;
Camera.Size previewSize = this.camera.getParameters().getPreviewSize();
previewWidth = previewSize.width;
previewHeight = previewSize.height;
previewBitmap = Bitmap.createBitmap(previewWidth, previewHeight, Bitmap.Config.ARGB_8888);
// Initialize Scale Variables
previewScaleMatrix = new Matrix();
previewScaleMatrix.setScale(deviceWidth/(float) previewWidth,
deviceHeight/(float) previewHeight, deviceWidth/2.0f, deviceHeight/2.0f);
// Initialize RenderScript variables
rs = RenderScript.create(getContext());
// RenderScript YUV to RGB
yuvToRgbScript = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
Type.Builder previewRgbaType =
new Type.Builder(rs, Element.RGBA_8888(rs)).setX(previewWidth).setY(previewHeight);
yuvToRgbOut = Allocation.createTyped(rs, previewRgbaType.create(), Allocation.USAGE_SCRIPT);
// RenderScript Invert
invertScript = new ScriptC_invert(rs);
invertOut = Allocation.createTyped(rs, yuvToRgbOut.getType(), Allocation.USAGE_SCRIPT);
// Set color effect to none
parameters.setColorEffect(Camera.Parameters.EFFECT_NONE);
camera.setParameters(parameters);
// Set the preview callback
Log.d(TAG, "#surfaceChanged() camera.setPreviewCallback()");
camera.setPreviewCallback(new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
Log.d(TAG, "#onPreviewFrame()");
}
});
// Start the camera preview
Log.d(TAG, "#surfaceChanged() camera.startPreview()");
camera.startPreview();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// Surface will be destroyed when replaced with a new screen
// Always make sure to release the Camera instance
if (camera != null) {
camera.setPreviewCallback(null);
camera.stopPreview();
camera.release();
camera = null;
}
}
LogCat màn hình của tôi như sau:
D/CameraSurfaceView: #surfaceChanged()
D/CameraSurfaceView: #surfaceChanged() camera.setPreviewCallback()
D/CameraSurfaceView: #surfaceChanged() camera.startPreview()
ScriptC_invert
là từ mẫu RenderScript
trong https://developer.android.com/guide/topics/renderscript/compute.html#writing-an-rs-kernel
Và ngay cả khi tôi xóa tất cả nội dung trên RenderScript, cùng một vấn đề.
Tôi cũng đã thử như sau:
LƯU Ý:
Một sửa chữa sẽ cần một camera.setPreviewDisplay(holder)
trong phương pháp surfaceChanged()
tôi. Nhưng điều này sẽ tạo ra một vấn đề khác đối với tôi kể từ khi tôi sẽ cần phải làm một holder.lockCanvas()
trong onPreviewFrame()
và gặp phải ngoại lệ sau đây:
E/SurfaceHolder: Exception locking surface
java.lang.IllegalArgumentException
at android.view.Surface.nativeLockCanvas(Native Method)
at android.view.Surface.lockCanvas(Surface.java:264)
at android.view.SurfaceView$4.internalLockCanvas(SurfaceView.java:842)
at android.view.SurfaceView$4.lockCanvas(SurfaceView.java:830)
at com.arcanys.ar.CameraSurfaceView.onPreviewFrame(CameraSurfaceView.java:204)
Có thể có một số điều mà tôi đã bỏ lỡ hoặc cấu hình sai.
Đây là giải pháp đúng. [setPreviewDisplay hoặc setPreviewTexture] (https://stackoverflow.com/questions/16752454/setpreviewdisplay-vs-setpreviewtexture) là bắt buộc trong Android, nhưng một số thiết bị không thực thi nó. –
BTW, hãy cân nhắc chuyển sang ** camera2 ** API trừ khi hầu hết các thiết bị mục tiêu của bạn ở dưới Lollipop. Và nếu bạn quyết định ở lại với API * không dùng nữa *, hãy đảm bảo bạn mở máy ảnh trong một chuỗi Trình xử lý riêng biệt (để Camera.open() và các cuộc gọi lại không gây tắc nghẽn trên chuỗi giao diện người dùng). –
@AlexCohn cảm ơn lời khuyên của bạn. Có, tôi cũng đang nhắm mục tiêu các thiết bị trước kẹo que, đây là lý do tôi vẫn sử dụng API máy ảnh không dùng nữa. – dhagz