优化Camera初始化相关策略,减少出现卡顿的可能性(#64,#65)

This commit is contained in:
jenly1314
2019-12-16 11:52:28 +08:00
parent c36ea8eb58
commit 2f4379cd7a
10 changed files with 87 additions and 71 deletions

View File

@@ -54,21 +54,21 @@ ZXingLite for Android 是ZXing的精简版基于ZXing库优化扫码和生成
<dependency> <dependency>
<groupId>com.king.zxing</groupId> <groupId>com.king.zxing</groupId>
<artifactId>zxing-lite</artifactId> <artifactId>zxing-lite</artifactId>
<version>1.1.4</version> <version>1.1.5</version>
<type>pom</type> <type>pom</type>
</dependency> </dependency>
``` ```
### Gradle: ### Gradle:
```gradle ```gradle
//AndroidX 版本 //AndroidX 版本
implementation 'com.king.zxing:zxing-lite:1.1.4-androidx' implementation 'com.king.zxing:zxing-lite:1.1.5-androidx'
//Android 版本 //Android 版本
implementation 'com.king.zxing:zxing-lite:1.1.4' implementation 'com.king.zxing:zxing-lite:1.1.5'
``` ```
### Lvy: ### Lvy:
```lvy ```lvy
<dependency org='com.king.zxing' name='zxing-lite' rev='1.1.4'> <dependency org='com.king.zxing' name='zxing-lite' rev='1.1.5'>
<artifact name='$AID' ext='pom'></artifact> <artifact name='$AID' ext='pom'></artifact>
</dependency> </dependency>
``` ```
@@ -98,9 +98,9 @@ api 'com.google.zxing:core:3.3.3'
布局示例 布局示例
> 可自定义布局覆写getLayoutId方法布局内至少要保证有SurfaceView和ViewfinderView控件id可根据覆写CaptureActivity 的 getSurfaceViewId 和 getViewfinderViewId方法自定义 > 可自定义布局覆写getLayoutId方法布局内至少要保证有SurfaceView和ViewfinderView控件id可根据覆写CaptureActivity 的 getSurfaceViewId 和 getViewfinderViewId方法自定义
> ivTorch为 v1.1.4版本新增的手电筒按钮如果想改ID可通过CaptureActivity中的getIvTorchId自定义ID > ivTorch为 v1.1.5版本新增的手电筒按钮如果想改ID可通过CaptureActivity中的getIvTorchId自定义ID
> 如果是从v1.1.4以前版本升级至v1.1.4以上版本请参考如下布局示例新增ivTorch也可忽略内置手电筒功能可直接将CaptureActivity中的getIvTorchId方法返回0 > 如果是从v1.1.5以前版本升级至v1.1.5以上版本请参考如下布局示例新增ivTorch也可忽略内置手电筒功能可直接将CaptureActivity中的getIvTorchId方法返回0
```Xml ```Xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
@@ -165,6 +165,9 @@ api 'com.google.zxing:core:3.3.3'
## 版本记录 ## 版本记录
#### v1.1.52019-12-16
* 优化Camera初始化相关策略减少出现卡顿的可能性
#### v1.1.42019-11-18 #### v1.1.42019-11-18
* 内置手电筒按钮,当光线太暗时,自动显示手电筒 (fix#58) * 内置手电筒按钮,当光线太暗时,自动显示手电筒 (fix#58)
* 生成二维码时Logo支持自定义大小 (fix#62) * 生成二维码时Logo支持自定义大小 (fix#62)
@@ -238,3 +241,5 @@ api 'com.google.zxing:core:3.3.3'
<img src="https://jenly1314.github.io/image/jenly666.png"> <img src="https://jenly1314.github.io/image/jenly666.png">
<img src="https://jenly1314.github.io/image/qqgourp.png"> <img src="https://jenly1314.github.io/image/qqgourp.png">
</div> </div>

Binary file not shown.

View File

@@ -1 +1 @@
[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":16,"versionName":"1.1.4-androidx","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}] [{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":18,"versionName":"1.1.5-androidx","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]

View File

@@ -5,6 +5,8 @@
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application <application
android:allowBackup="true" android:allowBackup="true"

View File

@@ -58,7 +58,7 @@ public class CustomCaptureActivity extends CaptureActivity {
// .framingRectHorizontalOffset(0)//设置识别区域水平方向偏移量,非全屏识别时才有效 // .framingRectHorizontalOffset(0)//设置识别区域水平方向偏移量,非全屏识别时才有效
.frontLightMode(FrontLightMode.AUTO)//设置闪光灯模式 .frontLightMode(FrontLightMode.AUTO)//设置闪光灯模式
.tooDarkLux(45f)//设置光线太暗时,自动触发开启闪光灯的照度值 .tooDarkLux(45f)//设置光线太暗时,自动触发开启闪光灯的照度值
.brightEnoughLux(450f)//设置光线足够明亮时,自动触发关闭闪光灯的照度值 .brightEnoughLux(100f)//设置光线足够明亮时,自动触发关闭闪光灯的照度值
.continuousScan(isContinuousScan);//是否连扫 .continuousScan(isContinuousScan);//是否连扫
} }

View File

@@ -110,7 +110,7 @@ public class CaptureHandler extends Handler implements ResultPointCallback {
quit.sendToTarget(); quit.sendToTarget();
try { try {
// Wait at most half a second; should be enough time, and onPause() will timeout quickly // Wait at most half a second; should be enough time, and onPause() will timeout quickly
decodeThread.join(500L); decodeThread.join(100L);
} catch (InterruptedException e) { } catch (InterruptedException e) {
// continue // continue
} }

View File

@@ -47,7 +47,7 @@ import androidx.fragment.app.Fragment;
/** /**
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a> * @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
*/ */
public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,CaptureManager { public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,CaptureManager, SurfaceHolder.Callback {
public static final String TAG = CaptureHelper.class.getSimpleName(); public static final String TAG = CaptureHelper.class.getSimpleName();
@@ -65,7 +65,6 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
private ViewfinderView viewfinderView; private ViewfinderView viewfinderView;
private SurfaceHolder surfaceHolder; private SurfaceHolder surfaceHolder;
private SurfaceHolder.Callback callback;
private View ivTorch; private View ivTorch;
private Collection<BarcodeFormat> decodeFormats; private Collection<BarcodeFormat> decodeFormats;
@@ -145,6 +144,8 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
*/ */
private OnCaptureCallback onCaptureCallback; private OnCaptureCallback onCaptureCallback;
private boolean hasCameraFlash;
/** /**
* use {@link #CaptureHelper(Fragment, SurfaceView, ViewfinderView, View)} * use {@link #CaptureHelper(Fragment, SurfaceView, ViewfinderView, View)}
* @param fragment * @param fragment
@@ -193,49 +194,8 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
beepManager = new BeepManager(activity); beepManager = new BeepManager(activity);
ambientLightManager = new AmbientLightManager(activity); ambientLightManager = new AmbientLightManager(activity);
cameraManager = new CameraManager(activity); hasCameraFlash = activity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
cameraManager.setFullScreenScan(isFullScreenScan); initCameraManager();
cameraManager.setFramingRectRatio(framingRectRatio);
cameraManager.setFramingRectVerticalOffset(framingRectVerticalOffset);
cameraManager.setFramingRectHorizontalOffset(framingRectHorizontalOffset);
if(ivTorch !=null && activity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)){
ivTorch.setOnClickListener(v -> cameraManager.setTorch(!ivTorch.isSelected()));
cameraManager.setOnSensorListener((torch, tooDark, ambientLightLux) -> {
if(tooDark){
if(ivTorch.getVisibility() != View.VISIBLE){
ivTorch.setVisibility(View.VISIBLE);
}
}else if(!torch){
if(ivTorch.getVisibility() == View.VISIBLE){
ivTorch.setVisibility(View.INVISIBLE);
}
}
});
cameraManager.setOnTorchListener(torch -> ivTorch.setSelected(torch));
}
callback = new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (holder == null) {
Log.e(TAG, "*** WARNING *** surfaceCreated() gave us a null surface!");
}
if (!hasSurface) {
hasSurface = true;
initCamera(holder);
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
hasSurface = false;
}
};
onCaptureListener = (result, barcode, scaleFactor) -> { onCaptureListener = (result, barcode, scaleFactor) -> {
inactivityTimer.onActivity(); inactivityTimer.onActivity();
@@ -257,17 +217,15 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
@Override @Override
public void onResume(){ public void onResume(){
beepManager.updatePrefs(); beepManager.updatePrefs();
ambientLightManager.start(cameraManager);
inactivityTimer.onResume(); inactivityTimer.onResume();
surfaceHolder.addCallback(callback);
if (hasSurface) { if (hasSurface) {
initCamera(surfaceHolder); initCamera(surfaceHolder);
} else { } else {
surfaceHolder.addCallback(callback); surfaceHolder.addCallback(this);
} }
ambientLightManager.start(cameraManager);
} }
@@ -282,7 +240,7 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
beepManager.close(); beepManager.close();
cameraManager.closeDriver(); cameraManager.closeDriver();
if (!hasSurface) { if (!hasSurface) {
surfaceHolder.removeCallback(callback); surfaceHolder.removeCallback(this);
} }
} }
@@ -327,6 +285,35 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
return false; return false;
} }
private void initCameraManager(){
cameraManager = new CameraManager(activity);
cameraManager.setFullScreenScan(isFullScreenScan);
cameraManager.setFramingRectRatio(framingRectRatio);
cameraManager.setFramingRectVerticalOffset(framingRectVerticalOffset);
cameraManager.setFramingRectHorizontalOffset(framingRectHorizontalOffset);
if(ivTorch !=null && hasCameraFlash){
ivTorch.setOnClickListener(v -> {
if(cameraManager!=null){
cameraManager.setTorch(!ivTorch.isSelected());
}
});
cameraManager.setOnSensorListener((torch, tooDark, ambientLightLux) -> {
if(tooDark){
if(ivTorch.getVisibility() != View.VISIBLE){
ivTorch.setVisibility(View.VISIBLE);
}
}else if(!torch){
if(ivTorch.getVisibility() == View.VISIBLE){
ivTorch.setVisibility(View.INVISIBLE);
}
}
});
cameraManager.setOnTorchListener(torch -> ivTorch.setSelected(torch));
}
}
/** /**
* 初始化Camera * 初始化Camera
* @param surfaceHolder * @param surfaceHolder
@@ -357,6 +344,27 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
} }
} }
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (holder == null) {
Log.e(TAG, "*** WARNING *** surfaceCreated() gave us a null surface!");
}
if (!hasSurface) {
hasSurface = true;
initCamera(holder);
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
hasSurface = false;
}
/** /**
* 处理变焦缩放 * 处理变焦缩放
* @param isZoomIn * @param isZoomIn
@@ -485,7 +493,8 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
onResult(result); onResult(result);
} }
/** /**';, mnb
*
* 接收扫码结果,想支持连扫时,可将{@link #continuousScan(boolean)}设置为{@code true} * 接收扫码结果,想支持连扫时,可将{@link #continuousScan(boolean)}设置为{@code true}
* 如果{@link #isContinuousScan}支持连扫,则默认重启扫码和解码器;当连扫逻辑太复杂时, * 如果{@link #isContinuousScan}支持连扫,则默认重启扫码和解码器;当连扫逻辑太复杂时,
* 请将{@link #autoRestartPreviewAndDecode(boolean)}设置为{@code false},并手动调用{@link #restartPreviewAndDecode()} * 请将{@link #autoRestartPreviewAndDecode(boolean)}设置为{@code false},并手动调用{@link #restartPreviewAndDecode()}

View File

@@ -50,7 +50,7 @@ final class InactivityTimer {
onActivity(); onActivity();
} }
synchronized void onActivity() { void onActivity() {
cancel(); cancel();
inactivityTask = new InactivityAsyncTask(activity); inactivityTask = new InactivityAsyncTask(activity);
try { try {
@@ -60,7 +60,7 @@ final class InactivityTimer {
} }
} }
synchronized void onPause() { void onPause() {
cancel(); cancel();
if (registered) { if (registered) {
activity.unregisterReceiver(powerStatusReceiver); activity.unregisterReceiver(powerStatusReceiver);
@@ -70,7 +70,7 @@ final class InactivityTimer {
} }
} }
synchronized void onResume() { void onResume() {
if (registered) { if (registered) {
Log.w(TAG, "PowerStatusReceiver was already registered?"); Log.w(TAG, "PowerStatusReceiver was already registered?");
} else { } else {
@@ -80,7 +80,7 @@ final class InactivityTimer {
onActivity(); onActivity();
} }
private synchronized void cancel() { private void cancel() {
AsyncTask<?,?,?> task = inactivityTask; AsyncTask<?,?,?> task = inactivityTask;
if (task != null) { if (task != null) {
task.cancel(true); task.cancel(true);

View File

@@ -90,7 +90,7 @@ public final class CameraManager {
* @param holder The surface object which the camera will draw preview frames into. * @param holder The surface object which the camera will draw preview frames into.
* @throws IOException Indicates the camera driver failed to open. * @throws IOException Indicates the camera driver failed to open.
*/ */
public synchronized void openDriver(SurfaceHolder holder) throws IOException { public void openDriver(SurfaceHolder holder) throws IOException {
OpenCamera theCamera = camera; OpenCamera theCamera = camera;
if (theCamera == null) { if (theCamera == null) {
theCamera = OpenCameraInterface.open(requestedCameraId); theCamera = OpenCameraInterface.open(requestedCameraId);
@@ -147,7 +147,7 @@ public final class CameraManager {
/** /**
* Closes the camera driver if still in use. * Closes the camera driver if still in use.
*/ */
public synchronized void closeDriver() { public void closeDriver() {
if (camera != null) { if (camera != null) {
camera.getCamera().release(); camera.getCamera().release();
camera = null; camera = null;
@@ -161,7 +161,7 @@ public final class CameraManager {
/** /**
* Asks the camera hardware to begin drawing preview frames to the screen. * Asks the camera hardware to begin drawing preview frames to the screen.
*/ */
public synchronized void startPreview() { public void startPreview() {
OpenCamera theCamera = camera; OpenCamera theCamera = camera;
if (theCamera != null && !previewing) { if (theCamera != null && !previewing) {
theCamera.getCamera().startPreview(); theCamera.getCamera().startPreview();
@@ -173,7 +173,7 @@ public final class CameraManager {
/** /**
* Tells the camera to stop drawing preview frames. * Tells the camera to stop drawing preview frames.
*/ */
public synchronized void stopPreview() { public void stopPreview() {
if (autoFocusManager != null) { if (autoFocusManager != null) {
autoFocusManager.stop(); autoFocusManager.stop();
autoFocusManager = null; autoFocusManager = null;

View File

@@ -1,7 +1,7 @@
//App //App
def app_version = [:] def app_version = [:]
app_version.versionCode = 16 app_version.versionCode = 18
app_version.versionName = "1.1.4-androidx" app_version.versionName = "1.1.5-androidx"
ext.app_version = app_version ext.app_version = app_version
//build version //build version