|
@@ -19,8 +19,13 @@ import com.google.zxing.ReaderException;
|
|
|
import com.google.zxing.common.HybridBinarizer;
|
|
|
|
|
|
import java.io.IOException;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Collection;
|
|
|
import java.util.Hashtable;
|
|
|
+import java.util.Iterator;
|
|
|
import java.util.List;
|
|
|
+import java.util.ListIterator;
|
|
|
+import java.util.Map;
|
|
|
|
|
|
import io.flutter.plugin.common.EventChannel;
|
|
|
import io.flutter.plugin.common.MethodChannel;
|
|
@@ -32,173 +37,112 @@ import static android.content.ContentValues.TAG;
|
|
|
import static java.security.AccessController.getContext;
|
|
|
|
|
|
|
|
|
-public class ScanView implements Camera.PreviewCallback,Runnable{
|
|
|
- private FlutterView view;
|
|
|
+public class ScanView {
|
|
|
private TextureRegistry.SurfaceTextureEntry textureEntry;
|
|
|
- private Camera camera;
|
|
|
- private Rect scanRect;
|
|
|
- private PluginRegistry.Registrar registrar;
|
|
|
- private MultiFormatReader multiFormatReader;
|
|
|
- private EventChannel.EventSink eventSink;
|
|
|
- private Handler resultHandler;
|
|
|
- private Thread decodeThread;
|
|
|
- private byte[] imageBytes;
|
|
|
-
|
|
|
- ScanView(FlutterView view,PluginRegistry.Registrar registrar,Rect viewRect,Rect scanRect, MethodChannel.Result result){
|
|
|
- this.view = view;
|
|
|
- this.registrar = registrar;
|
|
|
- this.scanRect = scanRect;
|
|
|
+ private Camera mCamera;
|
|
|
+ private DecodeHandler mDecodeHandler;
|
|
|
+
|
|
|
+ ScanView(FlutterView view,
|
|
|
+ PluginRegistry.Registrar registrar,
|
|
|
+ Rect viewRect,
|
|
|
+ Rect scanRect,
|
|
|
+ List<String> scanType,
|
|
|
+ MethodChannel.Result result) {
|
|
|
try {
|
|
|
- multiFormatReader = new MultiFormatReader();
|
|
|
- this.textureEntry = view.createSurfaceTexture();
|
|
|
- camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
|
|
|
- Camera.Parameters param = camera.getParameters();
|
|
|
- List<Camera.Size> sizes = param.getSupportedPreviewSizes();
|
|
|
+ mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
|
|
|
+ Camera.Parameters param = mCamera.getParameters();
|
|
|
param.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
|
|
|
param.setRotation(90);
|
|
|
- double viewRatio = viewRect.width() * 1.0 / viewRect.height();
|
|
|
- Camera.Size currentSize = sizes.get(0);
|
|
|
- double currentRatio = currentSize.width * 1.0 / currentSize.height;
|
|
|
- for(int i =1;i<sizes.size();i++){
|
|
|
- Camera.Size item= sizes.get(i);
|
|
|
- double diffOld = Math.abs(currentRatio - viewRatio);
|
|
|
- double diffNew = Math.abs(item.width * 1.0 / item.height - viewRatio);
|
|
|
- if(diffOld < diffNew){
|
|
|
- currentSize = item;
|
|
|
- currentRatio = item.width * 1.0 / item.height;
|
|
|
- }else if(diffOld == diffNew){
|
|
|
- if(item.height > currentSize.height){
|
|
|
- currentSize = item;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
|
|
|
- param.setPreviewSize(currentSize.width,currentSize.height); // 设置预览图像大小
|
|
|
- camera.setParameters(param);
|
|
|
- camera.setDisplayOrientation(90);
|
|
|
- camera.setPreviewTexture(textureEntry.surfaceTexture());
|
|
|
+ // 选择最合适的预览图像大小
|
|
|
+ Camera.Size currentSize = matchSize(viewRect, param);
|
|
|
+ // 设置预览图像大小
|
|
|
+ param.setPreviewSize(currentSize.width, currentSize.height);
|
|
|
+ mCamera.setParameters(param);
|
|
|
+ mCamera.setDisplayOrientation(90); //旋转90度,变成竖屏
|
|
|
+
|
|
|
+ //链接flutter纹理
|
|
|
+ this.textureEntry = view.createSurfaceTexture();
|
|
|
+ mCamera.setPreviewTexture(textureEntry.surfaceTexture());
|
|
|
+
|
|
|
+ //返回纹理ID
|
|
|
result.success(textureEntry.id());
|
|
|
- registerEventChannel();
|
|
|
- decodeThread = new Thread(this);
|
|
|
- decodeThread.start();
|
|
|
- resultHandler = new Handler() {
|
|
|
- @Override
|
|
|
- public void handleMessage(Message msg) {
|
|
|
- super.handleMessage(msg);
|
|
|
- switch (msg.what){
|
|
|
- case 1://继续扫描
|
|
|
- camera.setOneShotPreviewCallback(ScanView.this);
|
|
|
- break;
|
|
|
- case 2: //停止扫描
|
|
|
- eventSink.success((String) msg.obj);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- };
|
|
|
|
|
|
- }catch (Exception e) {
|
|
|
- result.error("ScanView init",e.getMessage(),null);
|
|
|
+ mDecodeHandler = new DecodeHandler(mCamera, scanType, scanRect);
|
|
|
+ mDecodeHandler.registerEventChannel(registrar, textureEntry.id());
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ result.error("ScanView init", e.getMessage(), null);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- void startScan(){
|
|
|
- camera.setOneShotPreviewCallback(this);
|
|
|
- camera.startPreview();;
|
|
|
+ void startScan() {
|
|
|
+ mCamera.setOneShotPreviewCallback(mDecodeHandler);
|
|
|
+ mCamera.startPreview();
|
|
|
+ ;
|
|
|
}
|
|
|
|
|
|
- void stopScan(){
|
|
|
- camera.setOneShotPreviewCallback(null);
|
|
|
- camera.stopPreview();
|
|
|
+ void stopScan() {
|
|
|
+ mCamera.setOneShotPreviewCallback(null);
|
|
|
+ mCamera.stopPreview();
|
|
|
}
|
|
|
|
|
|
- void release(){
|
|
|
- camera.release();
|
|
|
- camera = null;
|
|
|
- textureEntry.release();
|
|
|
- textureEntry = null;
|
|
|
+ /**
|
|
|
+ * 开灯
|
|
|
+ */
|
|
|
+ void turnOn() {
|
|
|
+ Camera.Parameters param = mCamera.getParameters();
|
|
|
+ param.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
|
|
|
+ mCamera.setParameters(param);
|
|
|
}
|
|
|
|
|
|
- private void registerEventChannel() {
|
|
|
- new EventChannel(
|
|
|
- registrar.messenger(), "fqreader/qrcodeEvents" + textureEntry.id())
|
|
|
- .setStreamHandler(
|
|
|
- new EventChannel.StreamHandler() {
|
|
|
- @Override
|
|
|
- public void onListen(Object arguments, EventChannel.EventSink eventSink) {
|
|
|
- ScanView.this.eventSink = eventSink;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void onCancel(Object arguments) {
|
|
|
- ScanView.this.eventSink = null;
|
|
|
- }
|
|
|
- });
|
|
|
+ /**
|
|
|
+ * 关灯
|
|
|
+ */
|
|
|
+ void turnOff() {
|
|
|
+ Camera.Parameters param = mCamera.getParameters();
|
|
|
+ param.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
|
|
|
+ mCamera.setParameters(param);
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
- public void onPreviewFrame(byte[] bytes, Camera camera) {
|
|
|
- synchronized (this){
|
|
|
- this.imageBytes = bytes;
|
|
|
- this.notify();
|
|
|
- }
|
|
|
+ void release() {
|
|
|
+ mCamera.release();
|
|
|
+ mCamera = null;
|
|
|
+ textureEntry.release();
|
|
|
+ textureEntry = null;
|
|
|
+ mDecodeHandler.release();
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- @Override
|
|
|
- public void run() {
|
|
|
- while (true) {
|
|
|
- try {
|
|
|
- synchronized (this) {
|
|
|
- this.wait();
|
|
|
- }
|
|
|
- Camera.Parameters parameters = camera.getParameters();
|
|
|
- Camera.Size size = parameters.getPreviewSize();
|
|
|
- int width = size.width;
|
|
|
- int height = size.height;
|
|
|
-
|
|
|
-
|
|
|
- com.google.zxing.Result rawResult = null;
|
|
|
- PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(imageBytes, width, height, scanRect.top, scanRect.left, scanRect.height(), scanRect.width(), false);
|
|
|
-
|
|
|
- BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
|
|
- try {
|
|
|
- rawResult = multiFormatReader.decode(bitmap);
|
|
|
- } catch (ReaderException re) {
|
|
|
- // continue
|
|
|
- } catch (NullPointerException npe) {
|
|
|
- // This is terrible
|
|
|
- } catch (ArrayIndexOutOfBoundsException aoe) {
|
|
|
-
|
|
|
- } finally {
|
|
|
- multiFormatReader.reset();
|
|
|
- }
|
|
|
-//
|
|
|
-// if (rawResult == null) {
|
|
|
-// LuminanceSource invertedSource = source.invert();
|
|
|
-// bitmap = new BinaryBitmap(new HybridBinarizer(invertedSource));
|
|
|
-// try {
|
|
|
-// rawResult = multiFormatReader.decodeWithState(bitmap);
|
|
|
-//
|
|
|
-// } catch (NotFoundException e) {
|
|
|
-// // continue
|
|
|
-// } finally {
|
|
|
-// multiFormatReader.reset();
|
|
|
-// }
|
|
|
-// }
|
|
|
-
|
|
|
- if (rawResult != null) {
|
|
|
- Message msg = new Message();
|
|
|
- msg.what = 2;
|
|
|
- msg.obj = rawResult.getText();
|
|
|
- this.resultHandler.sendMessage(msg);
|
|
|
- } else {
|
|
|
- Message msg = new Message();
|
|
|
- msg.what = 1;
|
|
|
- this.resultHandler.sendMessage(msg);
|
|
|
+ /**
|
|
|
+ * 选择最合适的预览图片大小
|
|
|
+ *
|
|
|
+ * @param viewRect
|
|
|
+ * @param param
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private Camera.Size matchSize(Rect viewRect, Camera.Parameters param) {
|
|
|
+ List<Camera.Size> sizes = param.getSupportedPreviewSizes();
|
|
|
+
|
|
|
+ double viewRatio = viewRect.width() * 1.0 / viewRect.height(); // 获取控件比例
|
|
|
+ Camera.Size currentSize = sizes.get(0);
|
|
|
+ double currentRatio = currentSize.width * 1.0 / currentSize.height; //获取第一个预览大小的比例
|
|
|
+
|
|
|
+ for (int i = 1; i < sizes.size(); i++) {
|
|
|
+ Camera.Size item = sizes.get(i);
|
|
|
+ double diffOld = Math.abs(currentRatio - viewRatio); //与控件比例的差异 旧
|
|
|
+ double diffNew = Math.abs(item.width * 1.0 / item.height - viewRatio); //与控件比例的差异 新
|
|
|
+
|
|
|
+ if (diffOld < diffNew) { //如果旧的小于新的则使用新的预览大小
|
|
|
+ currentSize = item;
|
|
|
+ currentRatio = item.width * 1.0 / item.height;
|
|
|
+ } else if (diffOld == diffNew) {
|
|
|
+ if (item.height > currentSize.height) { //如果一样且新的像素大于旧的,则用新的
|
|
|
+ currentSize = item;
|
|
|
}
|
|
|
- } catch (InterruptedException e) {
|
|
|
- e.printStackTrace();
|
|
|
}
|
|
|
}
|
|
|
+ return currentSize;
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
}
|