问题
Below is my barcode scanner activity, everything works fine except for the setAutoFocusEnabled(true). It returns a message on runtime that says my device does not support auto focus although the Samsung Tab E T561 is an auto focus enabled device.
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.util.SparseArray;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.EditText;
import com.google.android.gms.vision.CameraSource;
import com.google.android.gms.vision.Detector;
import com.google.android.gms.vision.barcode.Barcode;
import com.google.android.gms.vision.barcode.BarcodeDetector;
import java.io.IOException;
import static com.google.android.gms.vision.CameraSource.CAMERA_FACING_BACK;
import static com.google.android.gms.vision.CameraSource.CAMERA_FACING_FRONT;
public class ScanBarcodeActivity extends AppCompatActivity {
private String TAG = "ScanBarcodeActivity";
private BarcodeDetector barcodeDetector;
private SurfaceView cameraView;
private CameraSource cameraSource;
private EditText cardNo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scan_barcode);
}
@Override
protected void onResume() {
cameraView = (SurfaceView) findViewById(R.id.surfaceViewCamera);
cardNo = (EditText) findViewById(R.id.editTextBarcode);
scanBarcodeCam(0);
super.onResume();
}
@Override
protected void onDestroy() {
if(cameraSource != null) {
cameraSource.stop();
cameraSource.release();
cameraSource = null;
}
super.onDestroy();
}
public void switchCam(View view) {
if(cameraSource.getCameraFacing() == CAMERA_FACING_BACK) {
cameraSource.stop();
cameraSource.release();
cameraSource = null;
scanBarcodeCam(0);
Log.i(TAG, "switchCam to front");
} else {
cameraSource.stop();
cameraSource.release();
cameraSource = null;
scanBarcodeCam(1);
Log.i(TAG, "switchCam to back");
}
}
public void scanBarcodeCam(int cam) {
if(barcodeDetector == null) {
barcodeDetector = new BarcodeDetector.Builder(this)
.setBarcodeFormats(Barcode.EAN_13)
.build();
}
if(cam == 0) {
cameraSource = new CameraSource
.Builder(this, barcodeDetector)
.setRequestedPreviewSize(640, 480)
.setFacing(CAMERA_FACING_FRONT)
.setRequestedFps(30.0f)
.build();
} else if(cam == 1) {
cameraSource = new CameraSource
.Builder(this, barcodeDetector)
.setRequestedPreviewSize(640, 480)
.setFacing(CAMERA_FACING_BACK)
.setRequestedFps(30.0f)
.setAutoFocusEnabled(true)
.build();
}
if(!cameraView.getHolder().getSurface().isValid()) {
Log.i(TAG, "*** new SurfaceHolder");
cameraView.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
cameraSource.start(cameraView.getHolder());
} catch (IOException | RuntimeException e) {
Log.e(TAG, e.getMessage());
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (cameraSource != null) {
cameraSource.stop();
cameraSource.release();
cameraSource = null;
}
}
});
} else {
try {
cameraSource.start(cameraView.getHolder());
} catch(IOException e) {
Log.e(TAG, e.getMessage());
}
}
barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {
@Override
public void release() {
}
@Override
public void receiveDetections(Detector.Detections<Barcode> detections) {
final SparseArray<Barcode> barcodes = detections.getDetectedItems();
if(barcodes.size() != 0) {
cardNo.post(new Runnable() {
@Override
public void run() {
cardNo.setText(barcodes.valueAt(0).displayValue);
}
});
}
}
});
}
}
Any help would be highly appreciated.
回答1:
So after two days of struggle I finally managed to "concoct" a fix. But Android development team should seriously look into why setAutoFocusEnabled(true) doesn't work on devices with Auto Focus.
Here is my fix, hope it saves someone else some time:
@Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP) {
float x = event.getX();
float y = event.getY();
float touchMajor = event.getTouchMajor();
float touchMinor = event.getTouchMinor();
Rect touchRect = new Rect((int)(x - touchMajor / 2), (int)(y - touchMinor / 2), (int)(x + touchMajor / 2), (int)(y + touchMinor / 2));
this.submitFocusAreaRect(touchRect);
}
return super.onTouchEvent(event);
}
private void submitFocusAreaRect(final Rect touchRect) {
Field[] declaredFields = CameraSource.class.getDeclaredFields();
for (Field field : declaredFields) {
if (field.getType() == Camera.class) {
field.setAccessible(true);
try {
Camera camera = (Camera) field.get(cameraSource);
if (camera != null) {
Camera.Parameters cameraParameters = camera.getParameters();
if(cameraParameters.getMaxNumFocusAreas() == 0) {
return;
}
Rect focusArea = new Rect();
focusArea.set(touchRect.left * 2000 / cameraView.getWidth() - 1000,
touchRect.top * 2000 / cameraView.getHeight() - 1000,
touchRect.right * 2000 / cameraView.getWidth() - 1000,
touchRect.bottom * 2000 / cameraView.getHeight() - 1000);
ArrayList<Camera.Area> focusAreas = new ArrayList<>();
focusAreas.add(new Camera.Area(focusArea, 1000));
cameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
cameraParameters.setFocusAreas(focusAreas);
camera.setParameters(cameraParameters);
camera.autoFocus(this);
}
} catch (IllegalAccessException | RuntimeException e) {
e.getMessage();
}
break;
}
}
}
Now I can scan barcodes with the rear camera as well. Yay!
来源:https://stackoverflow.com/questions/41629911/camerasource-setautofocusenabledtrue-returns-camera-auto-focus-is-not-suppor