package com.king.zxing; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.util.DisplayMetrics; import android.view.MotionEvent; import android.view.View; import com.google.common.util.concurrent.ListenableFuture; import com.google.zxing.BarcodeFormat; import com.google.zxing.Result; import com.google.zxing.ResultPoint; import com.king.zxing.analyze.Analyzer; import com.king.zxing.analyze.MultiFormatAnalyzer; import com.king.zxing.util.LogUtils; import java.util.concurrent.Executors; import androidx.annotation.FloatRange; import androidx.annotation.Nullable; import androidx.camera.core.Camera; import androidx.camera.core.CameraSelector; import androidx.camera.core.ImageAnalysis; import androidx.camera.core.Preview; import androidx.camera.core.TorchState; import androidx.camera.lifecycle.ProcessCameraProvider; import androidx.camera.view.PreviewView; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.MutableLiveData; /** * @author Jenly */ public class DefaultCameraScan extends CameraScan { private FragmentActivity mFragmentActivity; private Context mContext; private LifecycleOwner mLifecycleOwner; private PreviewView mPreviewView; private ListenableFuture mCameraProviderFuture; private Camera mCamera; private CameraConfig mCameraConfig; private Analyzer mAnalyzer; /** * 是否分析 */ private volatile boolean isAnalyze = true; /** * 是否已经分析出结果 */ private volatile boolean isAnalyzeResult; private View flashlightView; private MutableLiveData mResultLiveData; private OnScanResultCallback mOnScanResultCallback; private BeepManager mBeepManager; private AmbientLightManager mAmbientLightManager; private int mScreenWidth; private int mScreenHeight; private long mLastAutoZoomTime; public DefaultCameraScan(FragmentActivity activity, PreviewView previewView){ this.mFragmentActivity = activity; this.mLifecycleOwner = activity; this.mContext = activity; this.mPreviewView = previewView; initData(); } public DefaultCameraScan(Fragment fragment, PreviewView previewView){ this.mFragmentActivity = fragment.getActivity(); this.mLifecycleOwner = fragment; this.mContext = fragment.getContext(); this.mPreviewView = previewView; initData(); } private void initData(){ mResultLiveData = new MutableLiveData<>(); mResultLiveData.observe(mLifecycleOwner, result -> { handleAnalyzeResult(result); }); mPreviewView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { LogUtils.d("click"); } }); mPreviewView.setOnTouchListener((v, event) -> onTouchEvent(event)); DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics(); mScreenWidth = displayMetrics.widthPixels; mScreenHeight = displayMetrics.heightPixels; mBeepManager = new BeepManager(mContext); mAmbientLightManager = new AmbientLightManager(mContext); if(mAmbientLightManager != null){ mAmbientLightManager.register(); mAmbientLightManager.setOnLightSensorEventListener((dark, lightLux) -> { if(flashlightView != null){ flashlightView.setSelected(!dark); if(dark){ if(flashlightView.getVisibility() != View.VISIBLE){ flashlightView.setVisibility(View.VISIBLE); } }else if(flashlightView.getVisibility() == View.VISIBLE){ flashlightView.setVisibility(View.INVISIBLE); } } }); } } private void initConfig(){ if(mCameraConfig == null){ mCameraConfig = new CameraConfig(); } if(mAnalyzer == null){ mAnalyzer = new MultiFormatAnalyzer(); } } @Override public CameraScan setCameraConfig(CameraConfig cameraConfig) { if(cameraConfig != null){ this.mCameraConfig = cameraConfig; } return this; } @Override public void startCamera(){ initConfig(); mCameraProviderFuture = ProcessCameraProvider.getInstance(mContext); mCameraProviderFuture.addListener(() -> { try{ Preview preview = mCameraConfig.options(new Preview.Builder()); //相机选择器 CameraSelector cameraSelector = mCameraConfig.options(new CameraSelector.Builder() .requireLensFacing(LENS_FACING_BACK)); //设置SurfaceProvider preview.setSurfaceProvider(mPreviewView.getSurfaceProvider()); //图像分析 ImageAnalysis imageAnalysis = mCameraConfig.options(new ImageAnalysis.Builder() .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)); imageAnalysis.setAnalyzer(Executors.newSingleThreadExecutor(), image -> { if(isAnalyze && !isAnalyzeResult && mAnalyzer != null){ Result result = mAnalyzer.analyze(image); if(result != null){ mResultLiveData.postValue(result); } } image.close(); }); if(mCamera != null){ mCameraProviderFuture.get().unbindAll(); } //绑定到生命周期 mCamera = mCameraProviderFuture.get().bindToLifecycle(mLifecycleOwner, cameraSelector, preview, imageAnalysis); }catch (Exception e){ LogUtils.e(e); } },ContextCompat.getMainExecutor(mContext)); } /** * 处理分析结果 * @param result */ private synchronized void handleAnalyzeResult(Result result){ if(isAnalyzeResult || !isAnalyze){ return; } isAnalyzeResult = true; if(mBeepManager != null){ mBeepManager.playBeepSoundAndVibrate(); } if(result.getBarcodeFormat() == BarcodeFormat.QR_CODE && isNeedAutoZoom() && mLastAutoZoomTime + 100 < System.currentTimeMillis()){ ResultPoint[] points = result.getResultPoints(); if(points != null && points.length >= 2){ float distance1 = ResultPoint.distance(points[0],points[1]); float maxDistance = distance1; if(points.length >= 3){ float distance2 = ResultPoint.distance(points[1],points[2]); float distance3 = ResultPoint.distance(points[0],points[2]); maxDistance = Math.max(Math.max(distance1,distance2),distance3); } if(handleAutoZoom((int)maxDistance,result)){ return; } } } scanResultCallback(result); } private boolean handleAutoZoom(int distance,Result result){ int size = Math.min(mScreenWidth,mScreenHeight); if(distance * 4 < size){ mLastAutoZoomTime = System.currentTimeMillis(); zoomIn(); scanResultCallback(result); return true; } return false; } private void scanResultCallback(Result result){ if(mOnScanResultCallback != null && mOnScanResultCallback.onScanResultCallback(result)){ //如果拦截了结果,则重置分析结果状态,直接可以连扫 isAnalyzeResult = false; return; } if(mFragmentActivity != null){ Intent intent = new Intent(); intent.putExtra(SCAN_RESULT,result.getText()); mFragmentActivity.setResult(Activity.RESULT_OK,intent); mFragmentActivity.finish(); } } @Override public void stopCamera(){ if(mCameraProviderFuture != null){ try { mCameraProviderFuture.get().unbindAll(); }catch (Exception e){ LogUtils.e(e); } } } @Override public CameraScan setAnalyzeImage(boolean analyze) { isAnalyze = analyze; return this; } /** * 设置分析器,如果内置的一些分析器不满足您的需求,你也可以自定义{@link Analyzer}, * 自定义时,切记需在{@link #startCamera()}之前调用才有效 * @param analyzer */ @Override public CameraScan setAnalyzer(Analyzer analyzer) { mAnalyzer = analyzer; return this; } @Override public void zoomIn(){ if(mCamera != null){ float ratio = mCamera.getCameraInfo().getZoomState().getValue().getZoomRatio() + 0.1f; float maxRatio = mCamera.getCameraInfo().getZoomState().getValue().getMaxZoomRatio(); if(ratio <= maxRatio){ mCamera.getCameraControl().setZoomRatio(ratio); } } } @Override public void zoomOut(){ if(mCamera != null){ float ratio = mCamera.getCameraInfo().getZoomState().getValue().getZoomRatio() - 0.1f; float minRatio = mCamera.getCameraInfo().getZoomState().getValue().getMinZoomRatio(); if(ratio >= minRatio){ mCamera.getCameraControl().setZoomRatio(ratio); } } } @Override public void zoomTo(float ratio) { if(mCamera != null){ mCamera.getCameraControl().setZoomRatio(ratio); } } @Override public void lineZoomIn() { if(mCamera != null){ float zoom = mCamera.getCameraInfo().getZoomState().getValue().getLinearZoom() + 0.1f; if(zoom <= 1f){ mCamera.getCameraControl().setLinearZoom(zoom); } } } @Override public void lineZoomOut() { if(mCamera != null){ float zoom = mCamera.getCameraInfo().getZoomState().getValue().getLinearZoom() - 0.1f; if(zoom >= 0f){ mCamera.getCameraControl().setLinearZoom(zoom); } } } @Override public void lineZoomTo(@FloatRange(from = 0.0,to = 1.0) float linearZoom) { if(mCamera != null){ mCamera.getCameraControl().setLinearZoom(linearZoom); } } @Override public CameraScan enableTorch(boolean torch) { if(mCamera != null && hasFlashUnit()){ mCamera.getCameraControl().enableTorch(torch); } return this; } @Override public boolean isTorchEnabled() { if(mCamera != null){ return mCamera.getCameraInfo().getTorchState().getValue() == TorchState.ON; } return false; } /** * 是否支持闪光灯 * @return */ @Override public boolean hasFlashUnit(){ if(mCamera != null){ return mCamera.getCameraInfo().hasFlashUnit(); } return false; } @Override public CameraScan setVibrate(boolean vibrate) { if(mBeepManager != null){ mBeepManager.setVibrate(vibrate); } return this; } @Override public CameraScan setPlayBeep(boolean playBeep) { if(mBeepManager != null){ mBeepManager.setPlayBeep(playBeep); } return this; } @Override public CameraScan setOnScanResultCallback(OnScanResultCallback callback) { this.mOnScanResultCallback = callback; return this; } @Nullable @Override public Camera getCamera(){ return mCamera; } @Override public void release() { isAnalyze = false; flashlightView = null; if(mAmbientLightManager != null){ mAmbientLightManager.unregister(); } if(mBeepManager != null){ mBeepManager.close(); } stopCamera(); } @Override public CameraScan bindFlashlightView(@Nullable View v) { flashlightView = v; if(mAmbientLightManager != null){ mAmbientLightManager.setLightSensorEnabled(v != null); } return this; } }