优化细节
This commit is contained in:
@@ -18,15 +18,12 @@ package com.king.zxing;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import com.king.zxing.camera.CameraManager;
|
||||
import com.king.zxing.camera.FrontLightMode;
|
||||
|
||||
/**
|
||||
* Detects ambient light and switches on the front light when very dark, and off again when sufficiently light.
|
||||
@@ -36,6 +33,8 @@ import com.king.zxing.camera.FrontLightMode;
|
||||
*/
|
||||
final class AmbientLightManager implements SensorEventListener {
|
||||
|
||||
private static final int INTERVAL_TIME = 200;
|
||||
|
||||
protected static final float TOO_DARK_LUX = 45.0f;
|
||||
protected static final float BRIGHT_ENOUGH_LUX = 100.0f;
|
||||
|
||||
@@ -52,19 +51,18 @@ final class AmbientLightManager implements SensorEventListener {
|
||||
private CameraManager cameraManager;
|
||||
private Sensor lightSensor;
|
||||
|
||||
private long lastTime;
|
||||
|
||||
AmbientLightManager(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
void start(CameraManager cameraManager) {
|
||||
this.cameraManager = cameraManager;
|
||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
if (FrontLightMode.readPref(sharedPrefs) == FrontLightMode.AUTO) {
|
||||
SensorManager sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
|
||||
lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
|
||||
if (lightSensor != null) {
|
||||
sensorManager.registerListener(this, lightSensor, SensorManager.SENSOR_DELAY_NORMAL);
|
||||
}
|
||||
SensorManager sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
|
||||
lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
|
||||
if (lightSensor != null) {
|
||||
sensorManager.registerListener(this, lightSensor, SensorManager.SENSOR_DELAY_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +77,12 @@ final class AmbientLightManager implements SensorEventListener {
|
||||
|
||||
@Override
|
||||
public void onSensorChanged(SensorEvent sensorEvent) {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
if(currentTime - lastTime < INTERVAL_TIME){//降低频率
|
||||
return;
|
||||
}
|
||||
lastTime = currentTime;
|
||||
|
||||
float ambientLightLux = sensorEvent.values[0];
|
||||
if (cameraManager != null) {
|
||||
if (ambientLightLux <= tooDarkLux) {
|
||||
|
||||
@@ -16,16 +16,13 @@ package com.king.zxing;
|
||||
*/
|
||||
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer;
|
||||
import android.os.Build;
|
||||
import android.os.Vibrator;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import com.king.zxing.util.LogUtils;
|
||||
|
||||
@@ -37,9 +34,7 @@ import java.io.IOException;
|
||||
*/
|
||||
public final class BeepManager implements MediaPlayer.OnErrorListener, Closeable {
|
||||
|
||||
private static final String TAG = BeepManager.class.getSimpleName();
|
||||
|
||||
private static final float BEEP_VOLUME = 0.10f;
|
||||
// private static final float BEEP_VOLUME = 0.10f;
|
||||
private static final long VIBRATE_DURATION = 200L;
|
||||
|
||||
private final Activity activity;
|
||||
@@ -62,8 +57,8 @@ public final class BeepManager implements MediaPlayer.OnErrorListener, Closeable
|
||||
}
|
||||
|
||||
synchronized void updatePrefs() {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||
shouldBeep(prefs, activity);
|
||||
// SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||
// shouldBeep(prefs, activity);
|
||||
// vibrate = prefs.getBoolean(Preferences.KEY_VIBRATE, false);
|
||||
if (playBeep && mediaPlayer == null) {
|
||||
// The volume on STREAM_SYSTEM is not adjustable, and users found it too loud,
|
||||
@@ -77,6 +72,7 @@ public final class BeepManager implements MediaPlayer.OnErrorListener, Closeable
|
||||
if (playBeep && mediaPlayer != null) {
|
||||
mediaPlayer.start();
|
||||
}
|
||||
LogUtils.d("vibrate:" + vibrate);
|
||||
if (vibrate) {
|
||||
Vibrator vibrator = (Vibrator) activity.getSystemService(Context.VIBRATOR_SERVICE);
|
||||
vibrator.vibrate(VIBRATE_DURATION);
|
||||
@@ -95,7 +91,6 @@ public final class BeepManager implements MediaPlayer.OnErrorListener, Closeable
|
||||
return shouldPlayBeep;
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||
private MediaPlayer buildMediaPlayer(Context activity) {
|
||||
MediaPlayer mediaPlayer = new MediaPlayer();
|
||||
try (AssetFileDescriptor file = activity.getResources().openRawResourceFd(R.raw.zxl_beep)) {
|
||||
@@ -103,7 +98,7 @@ public final class BeepManager implements MediaPlayer.OnErrorListener, Closeable
|
||||
mediaPlayer.setOnErrorListener(this);
|
||||
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
||||
mediaPlayer.setLooping(false);
|
||||
mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME);
|
||||
// mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME);
|
||||
mediaPlayer.prepare();
|
||||
return mediaPlayer;
|
||||
} catch (IOException ioe) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.view.MotionEvent;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
|
||||
import com.google.zxing.Result;
|
||||
import com.king.zxing.camera.CameraManager;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
@@ -62,7 +63,6 @@ public class CaptureActivity extends AppCompatActivity implements OnCaptureCallb
|
||||
int ivTorchId = getIvTorchId();
|
||||
if(ivTorchId != 0){
|
||||
ivTorch = findViewById(ivTorchId);
|
||||
ivTorch.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
initCaptureHelper();
|
||||
}
|
||||
@@ -161,7 +161,7 @@ public class CaptureActivity extends AppCompatActivity implements OnCaptureCallb
|
||||
* @return 返回true表示拦截,将不自动执行后续逻辑,为false表示不拦截,默认不拦截
|
||||
*/
|
||||
@Override
|
||||
public boolean onResultCallback(String result) {
|
||||
public boolean onResultCallback(Result result) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.google.zxing.Result;
|
||||
import com.king.zxing.camera.CameraManager;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
@@ -74,7 +75,6 @@ public class CaptureFragment extends Fragment implements OnCaptureCallback {
|
||||
int ivTorchId = getIvTorchId();
|
||||
if(ivTorchId != 0){
|
||||
ivTorch = mRootView.findViewById(ivTorchId);
|
||||
ivTorch.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
initCaptureHelper();
|
||||
}
|
||||
@@ -185,7 +185,7 @@ public class CaptureFragment extends Fragment implements OnCaptureCallback {
|
||||
* @return 返回true表示拦截,将不自动执行后续逻辑,为false表示不拦截,默认不拦截
|
||||
*/
|
||||
@Override
|
||||
public boolean onResultCallback(String result) {
|
||||
public boolean onResultCallback(Result result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ import java.util.Map;
|
||||
*/
|
||||
public class CaptureHandler extends Handler implements ResultPointCallback {
|
||||
|
||||
private static final String TAG = CaptureHandler.class.getSimpleName();
|
||||
|
||||
private final OnCaptureListener onCaptureListener;
|
||||
private final DecodeThread decodeThread;
|
||||
@@ -155,27 +154,13 @@ public class CaptureHandler extends Handler implements ResultPointCallback {
|
||||
*/
|
||||
private ResultPoint transform(ResultPoint originPoint) {
|
||||
Point screenPoint = cameraManager.getScreenResolution();
|
||||
Point cameraPoint = cameraManager.getCameraResolution();
|
||||
Point previewPoint = cameraManager.getPreviewSizeOnScreen();
|
||||
|
||||
float scaleX;
|
||||
float scaleY;
|
||||
float x;
|
||||
float y;
|
||||
|
||||
if(screenPoint.x < screenPoint.y){
|
||||
scaleX = 1.0f * screenPoint.x / cameraPoint.y;
|
||||
scaleY = 1.0f * screenPoint.y / cameraPoint.x;
|
||||
|
||||
x = originPoint.getX() * scaleX - Math.max(screenPoint.x,cameraPoint.y)/2;
|
||||
y = originPoint.getY() * scaleY - Math.min(screenPoint.y,cameraPoint.x)/2;
|
||||
}else{
|
||||
scaleX = 1.0f * screenPoint.x / cameraPoint.x;
|
||||
scaleY = 1.0f * screenPoint.y / cameraPoint.y;
|
||||
|
||||
x = originPoint.getX() * scaleX - Math.min(screenPoint.y,cameraPoint.y)/2;
|
||||
y = originPoint.getY() * scaleY - Math.max(screenPoint.x,cameraPoint.x)/2;
|
||||
}
|
||||
float scaleX = 1.0f * screenPoint.x / previewPoint.x;
|
||||
float scaleY = 1.0f * screenPoint.y / previewPoint.y;
|
||||
|
||||
float x = originPoint.getX() * scaleX - Math.min(screenPoint.y,previewPoint.y)/2;
|
||||
float y = originPoint.getY() * scaleY - Math.max(screenPoint.x,previewPoint.x)/2;
|
||||
|
||||
return new ResultPoint(x,y);
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.DecodeHintType;
|
||||
import com.google.zxing.Result;
|
||||
import com.king.zxing.camera.CameraManager;
|
||||
import com.king.zxing.camera.FrontLightMode;
|
||||
import com.king.zxing.util.LogUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -153,6 +152,11 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
|
||||
|
||||
private boolean hasCameraFlash;
|
||||
|
||||
/**
|
||||
* 是否启用光线传感器
|
||||
*/
|
||||
private boolean isAmbientLightEnabled = true;
|
||||
|
||||
/**
|
||||
* use {@link #CaptureHelper(Fragment, SurfaceView, ViewfinderView, View)}
|
||||
* @param fragment
|
||||
@@ -233,7 +237,10 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
|
||||
} else {
|
||||
surfaceHolder.addCallback(this);
|
||||
}
|
||||
ambientLightManager.start(cameraManager);
|
||||
if(isAmbientLightEnabled){
|
||||
ambientLightManager.start(cameraManager);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -244,7 +251,9 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
|
||||
captureHandler = null;
|
||||
}
|
||||
inactivityTimer.onPause();
|
||||
ambientLightManager.stop();
|
||||
if(isAmbientLightEnabled) {
|
||||
ambientLightManager.stop();
|
||||
}
|
||||
beepManager.close();
|
||||
cameraManager.closeDriver();
|
||||
if (!hasSurface) {
|
||||
@@ -491,7 +500,7 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
|
||||
* 重新启动扫码和解码器
|
||||
*/
|
||||
public void restartPreviewAndDecode(){
|
||||
if(captureHandler!=null){
|
||||
if(captureHandler != null){
|
||||
captureHandler.restartPreviewAndDecode();
|
||||
}
|
||||
}
|
||||
@@ -517,7 +526,7 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
|
||||
final String text = result.getText();
|
||||
if(isContinuousScan){
|
||||
if(onCaptureCallback!=null){
|
||||
onCaptureCallback.onResultCallback(text);
|
||||
onCaptureCallback.onResultCallback(result);
|
||||
}
|
||||
if(isAutoRestartPreviewAndDecode){
|
||||
restartPreviewAndDecode();
|
||||
@@ -528,7 +537,7 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
|
||||
if(isPlayBeep && captureHandler != null){//如果播放音效,则稍微延迟一点,给予播放音效时间
|
||||
captureHandler.postDelayed(() -> {
|
||||
//如果设置了回调,并且onCallback返回为true,则表示拦截
|
||||
if(onCaptureCallback!=null && onCaptureCallback.onResultCallback(text)){
|
||||
if(onCaptureCallback!=null && onCaptureCallback.onResultCallback(result)){
|
||||
return;
|
||||
}
|
||||
Intent intent = new Intent();
|
||||
@@ -541,7 +550,7 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
|
||||
}
|
||||
|
||||
//如果设置了回调,并且onCallback返回为true,则表示拦截
|
||||
if(onCaptureCallback!=null && onCaptureCallback.onResultCallback(text)){
|
||||
if(onCaptureCallback!=null && onCaptureCallback.onResultCallback(result)){
|
||||
return;
|
||||
}
|
||||
Intent intent = new Intent();
|
||||
@@ -662,23 +671,6 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置闪光灯模式。当设置模式为:{@link FrontLightMode#AUTO}时,如果满意默认的照度值范围,
|
||||
* 可通过{@link #tooDarkLux(float)}和{@link #brightEnoughLux(float)}来自定义照度范围,
|
||||
* 控制自动触发开启和关闭闪光灯。
|
||||
* 当设置模式非{@link FrontLightMode#AUTO}时,传感器不会检测,则不使用手电筒
|
||||
*
|
||||
* @param mode 默认:{@link FrontLightMode#AUTO}
|
||||
* @return
|
||||
*/
|
||||
public CaptureHelper frontLightMode(FrontLightMode mode) {
|
||||
FrontLightMode.put(activity,mode);
|
||||
if(ivTorch!=null && mode != FrontLightMode.AUTO){
|
||||
ivTorch.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置光线太暗时,自动显示手电筒按钮
|
||||
* @param tooDarkLux 默认:{@link AmbientLightManager#TOO_DARK_LUX}
|
||||
@@ -798,6 +790,16 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否启用光线传感器
|
||||
* @param isAmbientLightEnabled
|
||||
* @return
|
||||
*/
|
||||
public CaptureHelper ambientLightEnabled(boolean isAmbientLightEnabled){
|
||||
this.isAmbientLightEnabled = isAmbientLightEnabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置扫码回调
|
||||
|
||||
@@ -27,7 +27,6 @@ import android.os.Message;
|
||||
import android.view.Display;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.BinaryBitmap;
|
||||
import com.google.zxing.DecodeHintType;
|
||||
import com.google.zxing.MultiFormatReader;
|
||||
@@ -148,16 +147,22 @@ final class DecodeHandler extends Handler {
|
||||
long end = System.currentTimeMillis();
|
||||
LogUtils.d("Found barcode in " + (end - start) + " ms");
|
||||
|
||||
BarcodeFormat barcodeFormat = rawResult.getBarcodeFormat();
|
||||
if(handler!=null && handler.isSupportAutoZoom() && barcodeFormat == BarcodeFormat.QR_CODE){
|
||||
|
||||
if(handler.isSupportAutoZoom()){//是否支持自动放大
|
||||
ResultPoint[] resultPoints = rawResult.getResultPoints();
|
||||
if(resultPoints.length >= 3){
|
||||
float distance1 = ResultPoint.distance(resultPoints[0],resultPoints[1]);
|
||||
float distance2 = ResultPoint.distance(resultPoints[1],resultPoints[2]);
|
||||
float distance3 = ResultPoint.distance(resultPoints[0],resultPoints[2]);
|
||||
int maxDistance = (int)Math.max(Math.max(distance1,distance2),distance3);
|
||||
if(handleAutoZoom(maxDistance,width)){
|
||||
LogUtils.d("resultPoints:" +resultPoints.length);
|
||||
|
||||
final int length = resultPoints.length;
|
||||
if(length >= 2){//超过两个点则计算距离
|
||||
int ratio = 6;
|
||||
int maxDistance = (int)ResultPoint.distance(resultPoints[0],resultPoints[1]);
|
||||
if(length >= 3){
|
||||
float distance2 = ResultPoint.distance(resultPoints[1],resultPoints[2]);
|
||||
float distance3 = ResultPoint.distance(resultPoints[0],resultPoints[2]);
|
||||
maxDistance = (int)Math.max(Math.max(maxDistance,distance2),distance3);
|
||||
ratio = 5;
|
||||
}
|
||||
|
||||
if(handleAutoZoom(maxDistance,width,ratio)){//根据点之间的最大距离
|
||||
Message message = Message.obtain();
|
||||
message.what = R.id.decode_succeeded;
|
||||
message.obj = rawResult;
|
||||
@@ -170,23 +175,19 @@ final class DecodeHandler extends Handler {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (handler != null) {
|
||||
Message message = Message.obtain(handler, R.id.decode_succeeded, rawResult);
|
||||
if(handler.isReturnBitmap()){
|
||||
Bundle bundle = new Bundle();
|
||||
bundleThumbnail(source, bundle);
|
||||
message.setData(bundle);
|
||||
}
|
||||
message.sendToTarget();
|
||||
Message message = Message.obtain(handler, R.id.decode_succeeded, rawResult);
|
||||
if(handler.isReturnBitmap()){
|
||||
Bundle bundle = new Bundle();
|
||||
bundleThumbnail(source, bundle);
|
||||
message.setData(bundle);
|
||||
}
|
||||
message.sendToTarget();
|
||||
|
||||
} else {
|
||||
if (handler != null) {
|
||||
Message message = Message.obtain(handler, R.id.decode_failed);
|
||||
message.sendToTarget();
|
||||
}
|
||||
Message message = Message.obtain(handler, R.id.decode_failed);
|
||||
message.sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,12 +220,12 @@ final class DecodeHandler extends Handler {
|
||||
bundle.putFloat(DecodeThread.BARCODE_SCALED_FACTOR, (float) width / source.getWidth());
|
||||
}
|
||||
|
||||
private boolean handleAutoZoom(int length,int width){
|
||||
private boolean handleAutoZoom(int length,int width,int ratio){
|
||||
if(lastZoomTime > System.currentTimeMillis() - 1000){
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(length < width/ 5){
|
||||
if(length < width / ratio){
|
||||
|
||||
Camera camera = cameraManager.getOpenCamera().getCamera();
|
||||
if(camera!=null){
|
||||
|
||||
@@ -35,8 +35,6 @@ import java.util.concurrent.RejectedExecutionException;
|
||||
*/
|
||||
final class InactivityTimer {
|
||||
|
||||
private static final String TAG = InactivityTimer.class.getSimpleName();
|
||||
|
||||
private static final long INACTIVITY_DELAY_MS = 5 * 60 * 1000L;
|
||||
|
||||
private final Activity activity;
|
||||
@@ -106,7 +104,7 @@ final class InactivityTimer {
|
||||
// 0 indicates that we're on battery
|
||||
|
||||
InactivityTimer inactivityTimer = weakReference.get();
|
||||
if(inactivityTimer!=null){
|
||||
if(inactivityTimer != null){
|
||||
boolean onBatteryNow = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) <= 0;
|
||||
if (onBatteryNow) {
|
||||
inactivityTimer.onActivity();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.king.zxing;
|
||||
|
||||
|
||||
import com.google.zxing.Result;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
@@ -12,5 +13,5 @@ public interface OnCaptureCallback {
|
||||
* @param result 扫码结果
|
||||
* @return 返回true表示拦截,将不自动执行后续逻辑,为false表示不拦截
|
||||
*/
|
||||
boolean onResultCallback(String result);
|
||||
boolean onResultCallback(Result result);
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ public final class ViewfinderView extends View {
|
||||
|
||||
private static final int CURRENT_POINT_OPACITY = 0xA0;
|
||||
private static final int MAX_RESULT_POINTS = 20;
|
||||
private static final int POINT_SIZE = 20;
|
||||
private static final int POINT_SIZE = 30;
|
||||
|
||||
/**
|
||||
* 画笔
|
||||
@@ -176,7 +176,7 @@ public final class ViewfinderView extends View {
|
||||
private int frameLineWidth;
|
||||
|
||||
/**
|
||||
* 扫描动画延迟间隔时间 默认15毫秒
|
||||
* 扫描动画延迟间隔时间 默认20毫秒
|
||||
*/
|
||||
private int scannerAnimationDelay;
|
||||
|
||||
@@ -274,7 +274,7 @@ public final class ViewfinderView extends View {
|
||||
scannerLineMoveDistance = (int)array.getDimension(R.styleable.ViewfinderView_scannerLineMoveDistance,TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,2,getResources().getDisplayMetrics()));
|
||||
scannerLineHeight = (int)array.getDimension(R.styleable.ViewfinderView_scannerLineHeight,TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,5,getResources().getDisplayMetrics()));
|
||||
frameLineWidth = (int)array.getDimension(R.styleable.ViewfinderView_frameLineWidth,TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,getResources().getDisplayMetrics()));
|
||||
scannerAnimationDelay = array.getInteger(R.styleable.ViewfinderView_scannerAnimationDelay,15);
|
||||
scannerAnimationDelay = array.getInteger(R.styleable.ViewfinderView_scannerAnimationDelay,20);
|
||||
frameRatio = array.getFloat(R.styleable.ViewfinderView_frameRatio,0.625f);
|
||||
array.recycle();
|
||||
|
||||
|
||||
@@ -42,7 +42,6 @@ final class CameraConfigurationManager {
|
||||
private int cwNeededRotation;
|
||||
private int cwRotationFromDisplayToCamera;
|
||||
private Point screenResolution;
|
||||
private Point cameraResolution;
|
||||
private Point bestPreviewSize;
|
||||
private Point previewSizeOnScreen;
|
||||
|
||||
@@ -81,6 +80,7 @@ final class CameraConfigurationManager {
|
||||
throw new IllegalArgumentException("Bad rotation: " + displayRotation);
|
||||
}
|
||||
}
|
||||
|
||||
LogUtils.i("Display at: " + cwRotationFromNaturalToDisplay);
|
||||
|
||||
int cwRotationFromNaturalToCamera = camera.getOrientation();
|
||||
@@ -92,19 +92,6 @@ final class CameraConfigurationManager {
|
||||
LogUtils.i("Front camera overriden to: " + cwRotationFromNaturalToCamera);
|
||||
}
|
||||
|
||||
/*
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
String overrideRotationString;
|
||||
if (camera.getFacing() == CameraFacing.FRONT) {
|
||||
overrideRotationString = prefs.getString(PreferencesActivity.KEY_FORCE_CAMERA_ORIENTATION_FRONT, null);
|
||||
} else {
|
||||
overrideRotationString = prefs.getString(PreferencesActivity.KEY_FORCE_CAMERA_ORIENTATION, null);
|
||||
}
|
||||
if (overrideRotationString != null && !"-".equals(overrideRotationString)) {
|
||||
LogUtils.i("Overriding camera manually to " + overrideRotationString);
|
||||
cwRotationFromNaturalToCamera = Integer.parseInt(overrideRotationString);
|
||||
}
|
||||
*/
|
||||
|
||||
cwRotationFromDisplayToCamera = (360 + cwRotationFromNaturalToCamera - cwRotationFromNaturalToDisplay) % 360;
|
||||
LogUtils.i("Final display orientation: " + cwRotationFromDisplayToCamera);
|
||||
@@ -116,32 +103,26 @@ final class CameraConfigurationManager {
|
||||
}
|
||||
LogUtils.i("Clockwise rotation from display to camera: " + cwNeededRotation);
|
||||
|
||||
Point theScreenResolution = new Point();
|
||||
display.getSize(theScreenResolution);
|
||||
screenResolution = theScreenResolution;
|
||||
screenResolution = new Point();
|
||||
display.getSize(screenResolution);
|
||||
LogUtils.i("Screen resolution in current orientation: " + screenResolution);
|
||||
|
||||
cameraResolution = CameraConfigurationUtils.findBestPreviewSizeValue(parameters, screenResolution);
|
||||
LogUtils.i("Camera resolution: " + cameraResolution);
|
||||
bestPreviewSize = CameraConfigurationUtils.findBestPreviewSizeValue(parameters, screenResolution);
|
||||
LogUtils.i("Best available preview size: " + bestPreviewSize);
|
||||
|
||||
boolean isScreenPortrait = screenResolution.x < screenResolution.y;
|
||||
boolean isPreviewSizePortrait = bestPreviewSize.x < bestPreviewSize.y;
|
||||
|
||||
if (isScreenPortrait == isPreviewSizePortrait) {
|
||||
previewSizeOnScreen = bestPreviewSize;
|
||||
} else {
|
||||
if (isScreenPortrait) {
|
||||
previewSizeOnScreen = new Point(bestPreviewSize.y, bestPreviewSize.x);
|
||||
} else {
|
||||
previewSizeOnScreen = bestPreviewSize;
|
||||
}
|
||||
LogUtils.i("Preview size on screen: " + previewSizeOnScreen);
|
||||
|
||||
}
|
||||
|
||||
void setDesiredCameraParameters(OpenCamera camera, boolean safeMode) {
|
||||
|
||||
Camera theCamera = camera.getCamera();
|
||||
Camera.Parameters parameters = theCamera.getParameters();
|
||||
|
||||
if (parameters == null) {
|
||||
LogUtils.w("Device error: no camera parameters are available. Proceeding without configuration.");
|
||||
return;
|
||||
@@ -159,7 +140,7 @@ final class CameraConfigurationManager {
|
||||
parameters.setZoom(parameters.getMaxZoom() / 10);
|
||||
}
|
||||
|
||||
initializeTorch(parameters, prefs, safeMode);
|
||||
// initializeTorch(parameters, prefs, safeMode);
|
||||
|
||||
CameraConfigurationUtils.setFocus(
|
||||
parameters,
|
||||
@@ -189,9 +170,9 @@ final class CameraConfigurationManager {
|
||||
}
|
||||
|
||||
parameters.setPreviewSize(bestPreviewSize.x, bestPreviewSize.y);
|
||||
|
||||
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
|
||||
theCamera.setParameters(parameters);
|
||||
|
||||
theCamera.cancelAutoFocus();
|
||||
theCamera.setDisplayOrientation(cwRotationFromDisplayToCamera);
|
||||
|
||||
Camera.Parameters afterParameters = theCamera.getParameters();
|
||||
@@ -202,6 +183,7 @@ final class CameraConfigurationManager {
|
||||
bestPreviewSize.x = afterSize.width;
|
||||
bestPreviewSize.y = afterSize.height;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Point getBestPreviewSize() {
|
||||
@@ -212,10 +194,6 @@ final class CameraConfigurationManager {
|
||||
return previewSizeOnScreen;
|
||||
}
|
||||
|
||||
Point getCameraResolution() {
|
||||
return cameraResolution;
|
||||
}
|
||||
|
||||
Point getScreenResolution() {
|
||||
return screenResolution;
|
||||
}
|
||||
@@ -243,17 +221,16 @@ final class CameraConfigurationManager {
|
||||
camera.setParameters(parameters);
|
||||
}
|
||||
|
||||
private void initializeTorch(Camera.Parameters parameters, SharedPreferences prefs, boolean safeMode) {
|
||||
boolean currentSetting = FrontLightMode.readPref(prefs) == FrontLightMode.ON;
|
||||
doSetTorch(parameters, currentSetting, safeMode);
|
||||
private void initializeTorch(Camera.Parameters parameters, boolean safeMode) {
|
||||
doSetTorch(parameters, false, safeMode);
|
||||
}
|
||||
|
||||
private void doSetTorch(Camera.Parameters parameters, boolean newSetting, boolean safeMode) {
|
||||
CameraConfigurationUtils.setTorch(parameters, newSetting);
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
if (!safeMode && !prefs.getBoolean(Preferences.KEY_DISABLE_EXPOSURE, true)) {
|
||||
CameraConfigurationUtils.setBestExposure(parameters, newSetting);
|
||||
}
|
||||
// SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
// if (!safeMode && !prefs.getBoolean(Preferences.KEY_DISABLE_EXPOSURE, true)) {
|
||||
// CameraConfigurationUtils.setBestExposure(parameters, newSetting);
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import com.king.zxing.util.LogUtils;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -269,89 +270,56 @@ public final class CameraConfigurationUtils {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 预览尺寸与给定的宽高尺寸比较器。首先比较宽高的比例,在宽高比相同的情况下,根据宽和高的最小差进行比较。
|
||||
*/
|
||||
private static class SizeComparator implements Comparator<Camera.Size> {
|
||||
private final int width;
|
||||
private final int height;
|
||||
private final float ratio;
|
||||
SizeComparator(int width, int height) {
|
||||
//不管横屏还是竖屏,parameters.getSupportedPreviewSizes()的size.width 始终大于或等于 size.height
|
||||
if (width < height) {
|
||||
this.width = height;
|
||||
this.height = width;
|
||||
} else {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
this.ratio = (float) this.height / this.width;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(Camera.Size size1, Camera.Size size2) {
|
||||
int width1 = size1.width;
|
||||
int height1 = size1.height;
|
||||
int width2 = size2.width;
|
||||
int height2 = size2.height;
|
||||
float ratio1 = Math.abs((float) height1 / width1 - ratio);
|
||||
float ratio2 = Math.abs((float) height2 / width2 - ratio);
|
||||
int result = Float.compare(ratio1, ratio2);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
} else {
|
||||
int minGap1 = Math.abs(width - width1) + Math.abs(height - height1);
|
||||
int minGap2 = Math.abs(width - width2) + Math.abs(height - height2);
|
||||
return minGap1 - minGap2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 在Camera支持的预览尺寸中找到最佳的预览尺寸
|
||||
* @param parameters
|
||||
* @param screenResolution
|
||||
* @return
|
||||
*/
|
||||
public static Point findBestPreviewSizeValue(Camera.Parameters parameters,final Point screenResolution) {
|
||||
|
||||
List<Camera.Size> rawSupportedSizes = parameters.getSupportedPreviewSizes();
|
||||
if (rawSupportedSizes == null) {
|
||||
LogUtils.w( "Device returned no supported preview sizes; using default");
|
||||
Camera.Size defaultSize = parameters.getPreviewSize();
|
||||
if (defaultSize == null) {
|
||||
throw new IllegalStateException("Parameters contained no preview size!");
|
||||
}
|
||||
return new Point(defaultSize.width, defaultSize.height);
|
||||
}
|
||||
|
||||
|
||||
if (LogUtils.isShowLog()) {
|
||||
StringBuilder previewSizesString = new StringBuilder();
|
||||
for (Camera.Size size : rawSupportedSizes) {
|
||||
previewSizesString.append(size.width).append('x').append(size.height).append(' ');
|
||||
}
|
||||
LogUtils.d( "Supported preview sizes: " + previewSizesString);
|
||||
}
|
||||
|
||||
double screenAspectRatio;
|
||||
if(screenResolution.x < screenResolution.y){
|
||||
screenAspectRatio = screenResolution.x / (double) screenResolution.y;
|
||||
}else{
|
||||
screenAspectRatio = screenResolution.y / (double) screenResolution.x;
|
||||
}
|
||||
LogUtils.d( "screenAspectRatio: " + screenAspectRatio);
|
||||
// Find a suitable size, with max resolution
|
||||
int maxResolution = 0;
|
||||
|
||||
Camera.Size maxResPreviewSize = null;
|
||||
for (Camera.Size size : rawSupportedSizes) {
|
||||
int realWidth = size.width;
|
||||
int realHeight = size.height;
|
||||
int resolution = realWidth * realHeight;
|
||||
if (resolution < MIN_PREVIEW_PIXELS) {
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean isCandidatePortrait = realWidth < realHeight;
|
||||
int maybeFlippedWidth = isCandidatePortrait ? realWidth: realHeight ;
|
||||
int maybeFlippedHeight = isCandidatePortrait ? realHeight : realWidth;
|
||||
LogUtils.d( String.format("maybeFlipped:%d * %d",maybeFlippedWidth,maybeFlippedHeight));
|
||||
|
||||
double aspectRatio = maybeFlippedWidth / (double) maybeFlippedHeight;
|
||||
LogUtils.d( "aspectRatio: " + aspectRatio);
|
||||
double distortion = Math.abs(aspectRatio - screenAspectRatio);
|
||||
LogUtils.d( "distortion: " + distortion);
|
||||
if (distortion > MAX_ASPECT_DISTORTION) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (maybeFlippedWidth == screenResolution.x && maybeFlippedHeight == screenResolution.y) {
|
||||
Point exactPoint = new Point(realWidth, realHeight);
|
||||
LogUtils.d( "Found preview size exactly matching screen size: " + exactPoint);
|
||||
return exactPoint;
|
||||
}
|
||||
|
||||
// Resolution is suitable; record the one with max resolution
|
||||
if (resolution > maxResolution) {
|
||||
maxResolution = resolution;
|
||||
maxResPreviewSize = size;
|
||||
}
|
||||
}
|
||||
|
||||
// If no exact match, use largest preview size. This was not a great idea on older devices because
|
||||
// of the additional computation needed. We're likely to get here on newer Android 4+ devices, where
|
||||
// the CPU is much more powerful.
|
||||
if (maxResPreviewSize != null) {
|
||||
Point largestSize = new Point(maxResPreviewSize.width, maxResPreviewSize.height);
|
||||
LogUtils.d( "Using largest suitable preview size: " + largestSize);
|
||||
return largestSize;
|
||||
}
|
||||
|
||||
// If there is nothing at all suitable, return current preview size
|
||||
Camera.Size defaultPreview = parameters.getPreviewSize();
|
||||
if (defaultPreview == null) {
|
||||
throw new IllegalStateException("Parameters contained no preview size!");
|
||||
}
|
||||
Point defaultSize = new Point(defaultPreview.width, defaultPreview.height);
|
||||
LogUtils.d( "No suitable preview sizes, using default: " + defaultSize);
|
||||
return defaultSize;
|
||||
List<Camera.Size> preList = parameters.getSupportedPreviewSizes();
|
||||
Collections.sort(preList, new SizeComparator(screenResolution.x, screenResolution.y));
|
||||
Camera.Size size = preList.get(0);
|
||||
return new Point(size.width,size.height);
|
||||
}
|
||||
|
||||
private static String findSettableValue(String name,
|
||||
|
||||
@@ -168,7 +168,7 @@ public final class CameraManager {
|
||||
if (theCamera != null && !previewing) {
|
||||
theCamera.getCamera().startPreview();
|
||||
previewing = true;
|
||||
autoFocusManager = new AutoFocusManager(context, theCamera.getCamera());
|
||||
// autoFocusManager = new AutoFocusManager(context, theCamera.getCamera());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ public final class CameraManager {
|
||||
configManager.setTorch(theCamera.getCamera(), newSetting);
|
||||
if (wasAutoFocusManager) {
|
||||
autoFocusManager = new AutoFocusManager(context, theCamera.getCamera());
|
||||
autoFocusManager.start();
|
||||
// autoFocusManager.start();
|
||||
}
|
||||
|
||||
if(onTorchListener!=null){
|
||||
@@ -225,6 +225,7 @@ public final class CameraManager {
|
||||
* @param message The what field of the message to be sent.
|
||||
*/
|
||||
public synchronized void requestPreviewFrame(Handler handler, int message) {
|
||||
LogUtils.d("requestPreviewFrame");
|
||||
OpenCamera theCamera = camera;
|
||||
if (theCamera != null && previewing) {
|
||||
previewCallback.setHandler(handler, message);
|
||||
@@ -244,7 +245,7 @@ public final class CameraManager {
|
||||
if (camera == null) {
|
||||
return null;
|
||||
}
|
||||
Point point = configManager.getCameraResolution();
|
||||
Point point = configManager.getBestPreviewSize();
|
||||
if (point == null) {
|
||||
// Called early, before init even finished
|
||||
return null;
|
||||
@@ -281,22 +282,17 @@ public final class CameraManager {
|
||||
return null;
|
||||
}
|
||||
Rect rect = new Rect(framingRect);
|
||||
Point cameraResolution = configManager.getCameraResolution();
|
||||
Point preViewResolution = configManager.getPreviewSizeOnScreen();
|
||||
Point screenResolution = configManager.getScreenResolution();
|
||||
if (cameraResolution == null || screenResolution == null) {
|
||||
if (preViewResolution == null || screenResolution == null) {
|
||||
// Called early, before init even finished
|
||||
return null;
|
||||
}
|
||||
|
||||
// rect.left = rect.left * cameraResolution.x / screenResolution.x;
|
||||
// rect.right = rect.right * cameraResolution.x / screenResolution.x;
|
||||
// rect.top = rect.top * cameraResolution.y / screenResolution.y;
|
||||
// rect.bottom = rect.bottom * cameraResolution.y / screenResolution.y;
|
||||
|
||||
rect.left = rect.left * cameraResolution.y / screenResolution.x;
|
||||
rect.right = rect.right * cameraResolution.y / screenResolution.x;
|
||||
rect.top = rect.top * cameraResolution.x / screenResolution.y;
|
||||
rect.bottom = rect.bottom * cameraResolution.x / screenResolution.y;
|
||||
rect.left = rect.left * preViewResolution.x / screenResolution.x;
|
||||
rect.right = rect.right * preViewResolution.x / screenResolution.x;
|
||||
rect.top = rect.top * preViewResolution.y / screenResolution.y;
|
||||
rect.bottom = rect.bottom * preViewResolution.y / screenResolution.y;
|
||||
|
||||
|
||||
framingRectInPreview = rect;
|
||||
@@ -321,8 +317,12 @@ public final class CameraManager {
|
||||
this.framingRectHorizontalOffset = framingRectHorizontalOffset;
|
||||
}
|
||||
|
||||
public Point getCameraResolution() {
|
||||
return configManager.getCameraResolution();
|
||||
public Point getBestPreviewSize(){
|
||||
return configManager.getBestPreviewSize();
|
||||
}
|
||||
|
||||
public Point getPreviewSizeOnScreen() {
|
||||
return configManager.getPreviewSizeOnScreen();
|
||||
}
|
||||
|
||||
public Point getScreenResolution() {
|
||||
|
||||
@@ -44,7 +44,7 @@ final class PreviewCallback implements Camera.PreviewCallback {
|
||||
|
||||
@Override
|
||||
public void onPreviewFrame(byte[] data, Camera camera) {
|
||||
Point cameraResolution = configManager.getCameraResolution();
|
||||
Point cameraResolution = configManager.getBestPreviewSize();
|
||||
Handler thePreviewHandler = previewHandler;
|
||||
if (cameraResolution != null && thePreviewHandler != null) {
|
||||
Message message = thePreviewHandler.obtainMessage(previewMessage, cameraResolution.x,
|
||||
|
||||
@@ -59,6 +59,7 @@ public final class OpenCameraInterface {
|
||||
cameraId = 0;
|
||||
while (cameraId < numCameras) {
|
||||
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
|
||||
|
||||
Camera.getCameraInfo(cameraId, cameraInfo);
|
||||
if (CameraFacing.values()[cameraInfo.facing] == CameraFacing.BACK) {
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user