diff --git a/README.md b/README.md index 31fbb83..5a000b8 100644 --- a/README.md +++ b/README.md @@ -54,21 +54,21 @@ ZXingLite for Android 是ZXing的精简版,基于ZXing库优化扫码和生成 com.king.zxing zxing-lite - 1.1.3 + 1.1.4 pom ``` ### Gradle: ```gradle //AndroidX 版本 -implementation 'com.king.zxing:zxing-lite:1.1.3-androidx' +implementation 'com.king.zxing:zxing-lite:1.1.4-androidx' //Android 版本 -implementation 'com.king.zxing:zxing-lite:1.1.3' +implementation 'com.king.zxing:zxing-lite:1.1.4' ``` ### Lvy: ```lvy - + ``` @@ -95,7 +95,10 @@ api 'com.google.zxing:core:3.3.3' ## 示例 -布局示例 (可自定义布局,布局内至少要保证有SurfaceView和ViewfinderView,控件id可根据重写CaptureActivity 的 getPreviewViewId 和 getViewFinderViewId方法自定义) +布局示例 +> 可自定义布局,布局内至少要保证有SurfaceView和ViewfinderView,控件id可根据重写CaptureActivity 的 getSurfaceViewId 和 getViewfinderViewId方法自定义 +> ivTorch为 v1.1.4版本新增的手电筒按钮,如果想改ID可通过CaptureActivity中的getIvTorchId自定义ID + ```Xml - + ``` +或在你的布局中添加 + +```Xml + +``` + 代码示例 (二维码/条形码) ```Java //跳转的默认扫码界面 @@ -128,7 +143,8 @@ api 'com.google.zxing:core:3.3.3' ```Xml + android:screenOrientation="portrait" + android:theme="@style/CaptureTheme"/> ``` ### 快速实现扫码有以下几种方式: @@ -146,6 +162,10 @@ api 'com.google.zxing:core:3.3.3' ## 版本记录 +#### v1.1.4:2019-11-15 +* 内置手电筒按钮,当光线太暗时,自动显示手电筒 fix(#58) +* 生成二维码时Logo支持自定义大小 fix(#62) + #### v1.1.3:2019-9-24 * 支持真实识别区域比例和识别区域偏移量可配置 * 对外暴露更多可配置参数 diff --git a/app/release/app-release.apk b/app/release/app-release.apk index fb016aa..c551c8f 100644 Binary files a/app/release/app-release.apk and b/app/release/app-release.apk differ diff --git a/app/release/output.json b/app/release/output.json index f696025..a7d5c3a 100644 --- a/app/release/output.json +++ b/app/release/output.json @@ -1 +1 @@ -[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":14,"versionName":"1.1.3-androidx","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}] \ No newline at end of file +[{"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":{}}] \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 171b782..de8b4bd 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -23,21 +23,26 @@ + android:screenOrientation="portrait" + android:theme="@style/CaptureTheme"/> + android:screenOrientation="portrait" + android:theme="@style/CaptureTheme"/> + android:name=".CustomCaptureActivity" + android:theme="@style/CaptureTheme"/> + android:screenOrientation="portrait" + android:theme="@style/CaptureTheme"/> + android:screenOrientation="portrait" + android:theme="@style/CaptureTheme"/> { + //生成二维码相关放在子线程里面 + Bitmap logo = BitmapFactory.decodeResource(getResources(),R.drawable.logo); + Bitmap bitmap = CodeUtils.createQRCode(content,600,logo); + runOnUiThread(()->{ + //显示二维码 + ivCode.setImageBitmap(bitmap); + }); + }).start(); + } /** @@ -69,13 +74,18 @@ public class CodeActivity extends AppCompatActivity { * @param content */ private void createBarCode(String content){ - //生成条形码最好放子线程生成防止阻塞UI,这里只是演示 - Bitmap bitmap = CodeUtils.createBarCode(content, BarcodeFormat.CODE_128,800,200,null,true); - //显示条形码 - ivCode.setImageBitmap(bitmap); + new Thread(() -> { + //生成条形码相关放在子线程里面 + Bitmap bitmap = CodeUtils.createBarCode(content, BarcodeFormat.CODE_128,800,200,null,true); + runOnUiThread(()->{ + //显示条形码 + ivCode.setImageBitmap(bitmap); + }); + }).start(); } + public void onClick(View v){ switch (v.getId()){ case R.id.ivLeft: diff --git a/app/src/main/java/com/king/zxing/app/CustomActivity.java b/app/src/main/java/com/king/zxing/app/CustomActivity.java index ac7be02..0c6a44b 100644 --- a/app/src/main/java/com/king/zxing/app/CustomActivity.java +++ b/app/src/main/java/com/king/zxing/app/CustomActivity.java @@ -1,8 +1,7 @@ package com.king.zxing.app; -import android.hardware.Camera; -import android.os.Bundle; import android.app.Activity; +import android.os.Bundle; import android.view.MotionEvent; import android.view.SurfaceView; import android.view.View; @@ -33,6 +32,8 @@ public class CustomActivity extends AppCompatActivity implements OnCaptureCallba private ViewfinderView viewfinderView; + private View ivTorch; + @Override public void onCreate(Bundle icicle) { @@ -52,10 +53,12 @@ public class CustomActivity extends AppCompatActivity implements OnCaptureCallba surfaceView = findViewById(R.id.surfaceView); viewfinderView = findViewById(R.id.viewfinderView); + ivTorch = findViewById(R.id.ivFlash); + ivTorch.setVisibility(View.INVISIBLE); isContinuousScan = getIntent().getBooleanExtra(MainActivity.KEY_IS_CONTINUOUS,false); - mCaptureHelper = new CaptureHelper(this,surfaceView,viewfinderView); + mCaptureHelper = new CaptureHelper(this,surfaceView,viewfinderView,ivTorch); mCaptureHelper.setOnCaptureCallback(this); mCaptureHelper.onCreate(); mCaptureHelper.vibrate(true) @@ -89,26 +92,6 @@ public class CustomActivity extends AppCompatActivity implements OnCaptureCallba return super.onTouchEvent(event); } - /** - * 关闭闪光灯(手电筒) - */ - private void offFlash(){ - Camera camera = mCaptureHelper.getCameraManager().getOpenCamera().getCamera(); - Camera.Parameters parameters = camera.getParameters(); - parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); - camera.setParameters(parameters); - } - - /** - * 开启闪光灯(手电筒) - */ - public void openFlash(){ - Camera camera = mCaptureHelper.getCameraManager().getOpenCamera().getCamera(); - Camera.Parameters parameters = camera.getParameters(); - parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); - camera.setParameters(parameters); - } - /** * 扫码结果回调 @@ -124,25 +107,12 @@ public class CustomActivity extends AppCompatActivity implements OnCaptureCallba } - private void clickFlash(View v){ - if(v.isSelected()){ - offFlash(); - v.setSelected(false); - }else{ - openFlash(); - v.setSelected(true); - } - - } public void onClick(View v){ switch (v.getId()){ case R.id.ivLeft: onBackPressed(); break; - case R.id.ivFlash: - clickFlash(v); - break; } } } diff --git a/app/src/main/java/com/king/zxing/app/CustomCaptureActivity.java b/app/src/main/java/com/king/zxing/app/CustomCaptureActivity.java index bd84d5d..4a0819b 100644 --- a/app/src/main/java/com/king/zxing/app/CustomCaptureActivity.java +++ b/app/src/main/java/com/king/zxing/app/CustomCaptureActivity.java @@ -15,17 +15,14 @@ */ package com.king.zxing.app; -import android.content.pm.PackageManager; -import android.hardware.Camera; import android.os.Bundle; import android.view.View; -import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.king.zxing.CaptureActivity; import com.king.zxing.app.util.StatusBarUtils; -import com.king.zxing.camera.CameraConfigurationUtils; +import com.king.zxing.camera.FrontLightMode; import androidx.appcompat.widget.Toolbar; @@ -35,8 +32,6 @@ import androidx.appcompat.widget.Toolbar; */ public class CustomCaptureActivity extends CaptureActivity { - private ImageView ivFlash; - private boolean isContinuousScan; @Override public int getLayoutId() { @@ -52,12 +47,6 @@ public class CustomCaptureActivity extends CaptureActivity { TextView tvTitle = findViewById(R.id.tvTitle); tvTitle.setText(getIntent().getStringExtra(MainActivity.KEY_TITLE)); - ivFlash = findViewById(R.id.ivFlash); - - if(!hasTorch()){ - ivFlash.setVisibility(View.GONE); - } - isContinuousScan = getIntent().getBooleanExtra(MainActivity.KEY_IS_CONTINUOUS,false); //获取CaptureHelper,里面有扫码相关的配置设置 getCaptureHelper().playBeep(false)//播放音效 @@ -67,28 +56,12 @@ public class CustomCaptureActivity extends CaptureActivity { // .framingRectRatio(0.9f)//设置识别区域比例,范围建议在0.625 ~ 1.0之间。非全屏识别时才有效 // .framingRectVerticalOffset(0)//设置识别区域垂直方向偏移量,非全屏识别时才有效 // .framingRectHorizontalOffset(0)//设置识别区域水平方向偏移量,非全屏识别时才有效 + .frontLightMode(FrontLightMode.AUTO)//设置闪光灯模式 + .tooDarkLux(45f)//设置光线太暗时,自动触发开启闪光灯的照度值 + .brightEnoughLux(450f)//设置光线足够明亮时,自动触发关闭闪光灯的照度值 .continuousScan(isContinuousScan);//是否连扫 } - /** - * 开启或关闭闪光灯(手电筒) - * @param on {@code true}表示开启,{@code false}表示关闭 - */ - public void setTorch(boolean on){ - Camera camera = getCameraManager().getOpenCamera().getCamera(); - Camera.Parameters parameters = camera.getParameters(); - CameraConfigurationUtils.setTorch(parameters,on); - camera.setParameters(parameters); - - } - - /** - * 检测是否支持闪光灯(手电筒) - * @return - */ - public boolean hasTorch(){ - return getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH); - } /** * 扫码结果回调 @@ -104,21 +77,11 @@ public class CustomCaptureActivity extends CaptureActivity { return super.onResultCallback(result); } - - private void clickFlash(View v){ - boolean isSelected = v.isSelected(); - setTorch(!isSelected); - v.setSelected(!isSelected); - } - public void onClick(View v){ switch (v.getId()){ case R.id.ivLeft: onBackPressed(); break; - case R.id.ivFlash: - clickFlash(v); - break; } } } \ No newline at end of file diff --git a/app/src/main/java/com/king/zxing/app/MainActivity.java b/app/src/main/java/com/king/zxing/app/MainActivity.java index 7316e0f..cca76ec 100644 --- a/app/src/main/java/com/king/zxing/app/MainActivity.java +++ b/app/src/main/java/com/king/zxing/app/MainActivity.java @@ -94,7 +94,7 @@ public class MainActivity extends AppCompatActivity implements EasyPermissions.P } private void parsePhoto(Intent data){ - final String path = UriUtils.INSTANCE.getImagePath(this,data); + final String path = UriUtils.getImagePath(this,data); Log.d("Jenly","path:" + path); if(TextUtils.isEmpty(path)){ return; diff --git a/app/src/main/java/com/king/zxing/app/util/StatusBarUtils.java b/app/src/main/java/com/king/zxing/app/util/StatusBarUtils.java index 028308f..1c251a5 100644 --- a/app/src/main/java/com/king/zxing/app/util/StatusBarUtils.java +++ b/app/src/main/java/com/king/zxing/app/util/StatusBarUtils.java @@ -33,8 +33,11 @@ import androidx.appcompat.widget.Toolbar; /** * @author Jenly Jenly */ -public enum StatusBarUtils { - INSTANCE; +public final class StatusBarUtils { + + private StatusBarUtils(){ + throw new AssertionError(); + } public static void immersiveStatusBar(Activity activity, Toolbar toolbar) { immersiveStatusBar(activity,toolbar,0.0f); diff --git a/app/src/main/java/com/king/zxing/app/util/UriUtils.java b/app/src/main/java/com/king/zxing/app/util/UriUtils.java index ea8e899..a000452 100644 --- a/app/src/main/java/com/king/zxing/app/util/UriUtils.java +++ b/app/src/main/java/com/king/zxing/app/util/UriUtils.java @@ -1,6 +1,5 @@ package com.king.zxing.app.util; -import android.annotation.TargetApi; import android.content.ContentUris; import android.content.Context; import android.content.Intent; @@ -14,13 +13,16 @@ import android.util.Log; /** * @author Jenly Jenly */ -public enum UriUtils { - INSTANCE; +public final class UriUtils { + + private UriUtils(){ + throw new AssertionError(); + } /** * 获取图片 */ - public String getImagePath(Context context,Intent data) { + public static String getImagePath(Context context,Intent data) { String imagePath = null; Uri uri = data.getData(); //获取系統版本 @@ -54,7 +56,7 @@ public enum UriUtils { /** * 通过uri和selection来获取真实的图片路径,从相册获取图片时要用 */ - private String getImagePath(Context context,Uri uri, String selection) { + private static String getImagePath(Context context,Uri uri, String selection) { String path = null; Cursor cursor = context.getContentResolver().query(uri, null, selection, null, null); if (cursor != null) { diff --git a/app/src/main/res/drawable-xxhdpi/flash_off.png b/app/src/main/res/drawable-xxhdpi/flash_off.png index 6f351bf..0aa92fe 100644 Binary files a/app/src/main/res/drawable-xxhdpi/flash_off.png and b/app/src/main/res/drawable-xxhdpi/flash_off.png differ diff --git a/app/src/main/res/drawable-xxhdpi/flash_on.png b/app/src/main/res/drawable-xxhdpi/flash_on.png index 8213c66..bc321fe 100644 Binary files a/app/src/main/res/drawable-xxhdpi/flash_on.png and b/app/src/main/res/drawable-xxhdpi/flash_on.png differ diff --git a/app/src/main/res/layout/custom_activity.xml b/app/src/main/res/layout/custom_activity.xml index 85adc41..7822dbd 100644 --- a/app/src/main/res/layout/custom_activity.xml +++ b/app/src/main/res/layout/custom_activity.xml @@ -31,7 +31,6 @@ app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" - android:layout_marginTop="160dp" - style="@style/OnClick"/> + android:layout_marginTop="160dp" /> \ No newline at end of file diff --git a/app/src/main/res/layout/custom_capture_activity.xml b/app/src/main/res/layout/custom_capture_activity.xml index e44e0c3..76a6066 100644 --- a/app/src/main/res/layout/custom_capture_activity.xml +++ b/app/src/main/res/layout/custom_capture_activity.xml @@ -22,7 +22,7 @@ app:labelTextLocation="bottom" app:laserStyle="grid"/> + android:layout_marginTop="160dp" /> \ No newline at end of file diff --git a/lib/src/main/java/com/king/zxing/AmbientLightManager.java b/lib/src/main/java/com/king/zxing/AmbientLightManager.java index f6668a8..f5eb80b 100644 --- a/lib/src/main/java/com/king/zxing/AmbientLightManager.java +++ b/lib/src/main/java/com/king/zxing/AmbientLightManager.java @@ -36,8 +36,17 @@ import com.king.zxing.camera.FrontLightMode; */ final class AmbientLightManager implements SensorEventListener { - private static final float TOO_DARK_LUX = 45.0f; - private static final float BRIGHT_ENOUGH_LUX = 450.0f; + protected static final float TOO_DARK_LUX = 45.0f; + protected static final float BRIGHT_ENOUGH_LUX = 100.0f; + + /** + * 光线太暗时,默认:照度45 lux + */ + private float tooDarkLux = TOO_DARK_LUX; + /** + * 光线足够亮时,默认:照度450 lux + */ + private float brightEnoughLux = BRIGHT_ENOUGH_LUX; private final Context context; private CameraManager cameraManager; @@ -72,14 +81,22 @@ final class AmbientLightManager implements SensorEventListener { public void onSensorChanged(SensorEvent sensorEvent) { float ambientLightLux = sensorEvent.values[0]; if (cameraManager != null) { - if (ambientLightLux <= TOO_DARK_LUX) { - cameraManager.setTorch(true); - } else if (ambientLightLux >= BRIGHT_ENOUGH_LUX) { - cameraManager.setTorch(false); + if (ambientLightLux <= tooDarkLux) { + cameraManager.sensorChanged(true,ambientLightLux); + } else if (ambientLightLux >= brightEnoughLux) { + cameraManager.sensorChanged(false,ambientLightLux); } } } + public void setTooDarkLux(float tooDarkLux){ + this.tooDarkLux = tooDarkLux; + } + + public void setBrightEnoughLux(float brightEnoughLux){ + this.brightEnoughLux = brightEnoughLux; + } + @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // do nothing diff --git a/lib/src/main/java/com/king/zxing/CaptureActivity.java b/lib/src/main/java/com/king/zxing/CaptureActivity.java index 01a54a6..04400af 100644 --- a/lib/src/main/java/com/king/zxing/CaptureActivity.java +++ b/lib/src/main/java/com/king/zxing/CaptureActivity.java @@ -19,6 +19,7 @@ import android.app.Activity; import android.os.Bundle; import android.view.MotionEvent; import android.view.SurfaceView; +import android.view.View; import com.king.zxing.camera.CameraManager; @@ -32,6 +33,7 @@ public class CaptureActivity extends Activity implements OnCaptureCallback{ private SurfaceView surfaceView; private ViewfinderView viewfinderView; + private View ivTorch; private CaptureHelper mCaptureHelper; @@ -51,7 +53,12 @@ public class CaptureActivity extends Activity implements OnCaptureCallback{ public void initUI(){ surfaceView = findViewById(getSurfaceViewId()); viewfinderView = findViewById(getViewfinderViewId()); - mCaptureHelper = new CaptureHelper(this,surfaceView,viewfinderView); + int ivTorchId = getIvTorchId(); + if(ivTorchId != 0){ + ivTorch = findViewById(ivTorchId); + ivTorch.setVisibility(View.INVISIBLE); + } + mCaptureHelper = new CaptureHelper(this,surfaceView,viewfinderView,ivTorch); mCaptureHelper.setOnCaptureCallback(this); mCaptureHelper.onCreate(); } @@ -74,7 +81,7 @@ public class CaptureActivity extends Activity implements OnCaptureCallback{ } /** - * {@link ViewfinderView} 的 id + * {@link #viewfinderView} 的 ID * @return */ public int getViewfinderViewId(){ @@ -83,13 +90,21 @@ public class CaptureActivity extends Activity implements OnCaptureCallback{ /** - * 预览界面{@link #surfaceView} 的id + * 预览界面{@link #surfaceView} 的ID * @return */ public int getSurfaceViewId(){ return R.id.surfaceView; } + /** + * 获取 {@link #ivTorch} 的ID + * @return 默认返回{@code R.id.ivTorch}, 如果不需要手电筒按钮可以返回0 + */ + public int getIvTorchId(){ + return R.id.ivTorch; + } + /** * Get {@link CaptureHelper} * @return {@link #mCaptureHelper} diff --git a/lib/src/main/java/com/king/zxing/CaptureFragment.java b/lib/src/main/java/com/king/zxing/CaptureFragment.java index 1f39497..3fdd75f 100644 --- a/lib/src/main/java/com/king/zxing/CaptureFragment.java +++ b/lib/src/main/java/com/king/zxing/CaptureFragment.java @@ -38,6 +38,7 @@ public class CaptureFragment extends Fragment implements OnCaptureCallback { private SurfaceView surfaceView; private ViewfinderView viewfinderView; + private View ivTorch; private CaptureHelper mCaptureHelper; @@ -67,7 +68,12 @@ public class CaptureFragment extends Fragment implements OnCaptureCallback { public void initUI(){ surfaceView = mRootView.findViewById(getSurfaceViewId()); viewfinderView = mRootView.findViewById(getViewfinderViewId()); - mCaptureHelper = new CaptureHelper(this,surfaceView,viewfinderView); + int ivTorchId = getIvTorchId(); + if(ivTorchId != 0){ + ivTorch = mRootView.findViewById(ivTorchId); + ivTorch.setVisibility(View.INVISIBLE); + } + mCaptureHelper = new CaptureHelper(this,surfaceView,viewfinderView,ivTorch); mCaptureHelper.setOnCaptureCallback(this); } @@ -96,7 +102,6 @@ public class CaptureFragment extends Fragment implements OnCaptureCallback { return R.id.viewfinderView; } - /** * 预览界面{@link #surfaceView} 的id * @return @@ -105,6 +110,14 @@ public class CaptureFragment extends Fragment implements OnCaptureCallback { return R.id.surfaceView; } + /** + * 获取 {@link #ivTorch} 的ID + * @return 默认返回{@code R.id.ivTorch}, 如果不需要手电筒按钮可以返回0 + */ + public int getIvTorchId(){ + return R.id.ivTorch; + } + /** * Get {@link CaptureHelper} * @return {@link #mCaptureHelper} diff --git a/lib/src/main/java/com/king/zxing/CaptureHelper.java b/lib/src/main/java/com/king/zxing/CaptureHelper.java index 9f60602..604cf2c 100644 --- a/lib/src/main/java/com/king/zxing/CaptureHelper.java +++ b/lib/src/main/java/com/king/zxing/CaptureHelper.java @@ -17,6 +17,7 @@ package com.king.zxing; import android.app.Activity; import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Rect; import android.graphics.RectF; import android.hardware.Camera; @@ -24,11 +25,13 @@ import android.util.Log; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; +import android.view.View; 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 java.io.IOException; import java.util.ArrayList; @@ -62,6 +65,7 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture private ViewfinderView viewfinderView; private SurfaceHolder surfaceHolder; private SurfaceHolder.Callback callback; + private View ivTorch; private Collection decodeFormats; private Map decodeHints; @@ -127,21 +131,58 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture * 识别区域水平方向偏移量 */ private int framingRectHorizontalOffset; - + /** + * 光线太暗,当光线亮度太暗,亮度低于此值时,显示手电筒按钮 + */ + private float tooDarkLux = AmbientLightManager.TOO_DARK_LUX; + /** + * 光线足够明亮,当光线亮度足够明亮,亮度高于此值时,隐藏手电筒按钮 + */ + private float brightEnoughLux = AmbientLightManager.BRIGHT_ENOUGH_LUX; + /** + * 扫码回调 + */ private OnCaptureCallback onCaptureCallback; - + /** + * use {@link #CaptureHelper(Fragment, SurfaceView, ViewfinderView, View)} + * @param fragment + * @param surfaceView + * @param viewfinderView + */ + @Deprecated public CaptureHelper(Fragment fragment, SurfaceView surfaceView, ViewfinderView viewfinderView){ - this(fragment.getActivity(),surfaceView,viewfinderView); - + this(fragment,surfaceView,viewfinderView,null); } + public CaptureHelper(Fragment fragment, SurfaceView surfaceView, ViewfinderView viewfinderView,View ivTorch){ + this(fragment.getActivity(),surfaceView,viewfinderView,ivTorch); + } + + /** + * use {@link #CaptureHelper(Activity, SurfaceView, ViewfinderView, View)} + * @param activity + * @param surfaceView + * @param viewfinderView + */ + @Deprecated public CaptureHelper(Activity activity,SurfaceView surfaceView,ViewfinderView viewfinderView){ + this(activity,surfaceView,viewfinderView,null); + } + + /** + * + * @param activity + * @param surfaceView + * @param viewfinderView + * @param ivTorch + */ + public CaptureHelper(Activity activity,SurfaceView surfaceView,ViewfinderView viewfinderView,View ivTorch){ this.activity = activity; this.viewfinderView = viewfinderView; + this.ivTorch = ivTorch; surfaceHolder = surfaceView.getHolder(); hasSurface = false; - } @@ -156,6 +197,22 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture 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) { @@ -187,6 +244,11 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture //设置是否播放音效和震动 beepManager.setPlayBeep(isPlayBeep); beepManager.setVibrate(isVibrate); + + //设置闪光灯的太暗时和足够亮时的照度值 + ambientLightManager.setTooDarkLux(tooDarkLux); + ambientLightManager.setBrightEnoughLux(brightEnoughLux); + } @@ -566,6 +628,49 @@ 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} + * @return + */ + public CaptureHelper tooDarkLux(float tooDarkLux) { + this.tooDarkLux = tooDarkLux; + if(ambientLightManager != null){ + ambientLightManager.setTooDarkLux(tooDarkLux); + } + return this; + } + + /** + * 设置光线足够明亮时,自动隐藏手电筒按钮 + * @param brightEnoughLux 默认:{@link AmbientLightManager#BRIGHT_ENOUGH_LUX} + * @return + */ + public CaptureHelper brightEnoughLux(float brightEnoughLux) { + this.brightEnoughLux = brightEnoughLux; + if(ambientLightManager != null){ + ambientLightManager.setTooDarkLux(tooDarkLux); + } + return this; + } + /** * 设置返回扫码原图 * @param returnBitmap 默认为false,当返回true表示扫码就结果会返回扫码原图,相应的会增加性能消耗。 diff --git a/lib/src/main/java/com/king/zxing/camera/CameraManager.java b/lib/src/main/java/com/king/zxing/camera/CameraManager.java index ad87708..46e85f6 100644 --- a/lib/src/main/java/com/king/zxing/camera/CameraManager.java +++ b/lib/src/main/java/com/king/zxing/camera/CameraManager.java @@ -73,6 +73,11 @@ public final class CameraManager { */ private final PreviewCallback previewCallback; + private OnTorchListener onTorchListener; + private OnSensorListener onSensorListener; + + private boolean isTorch; + public CameraManager(Context context) { this.context = context.getApplicationContext(); this.configManager = new CameraConfigurationManager(context); @@ -193,14 +198,22 @@ public final class CameraManager { autoFocusManager.stop(); autoFocusManager = null; } + this.isTorch = newSetting; configManager.setTorch(theCamera.getCamera(), newSetting); if (wasAutoFocusManager) { autoFocusManager = new AutoFocusManager(context, theCamera.getCamera()); autoFocusManager.start(); } + + if(onTorchListener!=null){ + onTorchListener.onTorchChanged(newSetting); + } + } + } + /** * A single preview frame will be returned to the handler supplied. The data will arrive as byte[] * in the message.obj field, with width and height encoded as message.arg1 and message.arg2, @@ -377,4 +390,49 @@ public final class CameraManager { size, size, false); } + /** + * 提供闪光灯监听 + * @param listener + */ + public void setOnTorchListener(OnTorchListener listener){ + this.onTorchListener = listener; + } + + /** + * 传感器光线照度监听 + * @param listener + */ + public void setOnSensorListener(OnSensorListener listener){ + this.onSensorListener = listener; + } + + public void sensorChanged(boolean tooDark,float ambientLightLux){ + if(onSensorListener!=null){ + onSensorListener.onSensorChanged(isTorch,tooDark,ambientLightLux); + } + } + + public interface OnTorchListener{ + /** + * 当闪光灯状态改变时触发 + * @param torch true表示开启、false表示关闭 + */ + void onTorchChanged(boolean torch); + } + + + /** + * 传感器灯光亮度监听 + */ + public interface OnSensorListener{ + /** + * + * @param torch 闪光灯是否开启 + * @param tooDark 传感器检测到的光线亮度,是否太暗 + * @param ambientLightLux 光线照度 + */ + void onSensorChanged(boolean torch,boolean tooDark,float ambientLightLux); + } + + } \ No newline at end of file diff --git a/lib/src/main/java/com/king/zxing/camera/FrontLightMode.java b/lib/src/main/java/com/king/zxing/camera/FrontLightMode.java index a332621..c59494c 100644 --- a/lib/src/main/java/com/king/zxing/camera/FrontLightMode.java +++ b/lib/src/main/java/com/king/zxing/camera/FrontLightMode.java @@ -16,7 +16,9 @@ package com.king.zxing.camera; */ +import android.content.Context; import android.content.SharedPreferences; +import android.preference.PreferenceManager; import com.king.zxing.Preferences; @@ -33,11 +35,16 @@ public enum FrontLightMode { OFF; private static FrontLightMode parse(String modeString) { - return modeString == null ? OFF : valueOf(modeString); + return modeString == null ? AUTO : valueOf(modeString); } public static FrontLightMode readPref(SharedPreferences sharedPrefs) { - return parse(sharedPrefs.getString(Preferences.KEY_FRONT_LIGHT_MODE, OFF.toString())); + return parse(sharedPrefs.getString(Preferences.KEY_FRONT_LIGHT_MODE, AUTO.toString())); + } + + public static void put(Context context, FrontLightMode mode) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + prefs.edit().putString(Preferences.KEY_FRONT_LIGHT_MODE, mode.toString()).commit(); } } \ No newline at end of file diff --git a/lib/src/main/java/com/king/zxing/util/CodeUtils.java b/lib/src/main/java/com/king/zxing/util/CodeUtils.java index 574ad16..3563f2f 100644 --- a/lib/src/main/java/com/king/zxing/util/CodeUtils.java +++ b/lib/src/main/java/com/king/zxing/util/CodeUtils.java @@ -46,13 +46,14 @@ import java.util.Map; import java.util.Vector; import androidx.annotation.ColorInt; +import androidx.annotation.FloatRange; import androidx.annotation.NonNull; /** * @author Jenly Jenly */ -public class CodeUtils { +public final class CodeUtils { private CodeUtils(){ throw new AssertionError(); @@ -60,8 +61,8 @@ public class CodeUtils { /** * 生成二维码 - * @param content - * @param heightPix + * @param content 二维码的内容 + * @param heightPix 二维码的高 * @return */ public static Bitmap createQRCode(String content, int heightPix) { @@ -69,13 +70,25 @@ public class CodeUtils { } /** - * 生成二维码 - * @param content - * @param heightPix - * @param logo + * 生成我二维码 + * @param content 二维码的内容 + * @param heightPix 二维码的高 + * @param logo logo大小默认占二维码的20% * @return */ public static Bitmap createQRCode(String content, int heightPix, Bitmap logo) { + return createQRCode(content,heightPix,logo,0.2f); + } + + /** + * 生成二维码 + * @param content 二维码的内容 + * @param heightPix 二维码的高 + * @param logo 二维码中间的logo + * @param ratio logo所占比例 因为二维码的最大容错率为30%,所以建议ratio的范围小于0.3 + * @return + */ + public static Bitmap createQRCode(String content, int heightPix, Bitmap logo,@FloatRange(from = 0.0f,to = 1.0f)float ratio) { //配置参数 Map hints = new HashMap<>(); hints.put( EncodeHintType.CHARACTER_SET, "utf-8"); @@ -83,18 +96,19 @@ public class CodeUtils { hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); //设置空白边距的宽度 hints.put(EncodeHintType.MARGIN, 1); //default is 4 - return createQRCode(content,heightPix,logo,hints); + return createQRCode(content,heightPix,logo,ratio,hints); } /** * 生成二维码 - * @param content - * @param heightPix - * @param logo + * @param content 二维码的内容 + * @param heightPix 二维码的高 + * @param logo 二维码中间的logo + * @param ratio logo所占比例 因为二维码的最大容错率为30%,所以建议ratio的范围小于0.3 * @param hints * @return */ - public static Bitmap createQRCode(String content, int heightPix, Bitmap logo,Map hints) { + public static Bitmap createQRCode(String content, int heightPix, Bitmap logo,@FloatRange(from = 0.0f,to = 1.0f)float ratio,Map hints) { try { // 图像数据转换,使用了矩阵转换 @@ -117,7 +131,7 @@ public class CodeUtils { bitmap.setPixels(pixels, 0, heightPix, 0, 0, heightPix, heightPix); if (logo != null) { - bitmap = addLogo(bitmap, logo); + bitmap = addLogo(bitmap, logo,ratio); } return bitmap; @@ -130,8 +144,12 @@ public class CodeUtils { /** * 在二维码中间添加Logo图案 + * @param src + * @param logo + * @param ratio logo所占比例 因为二维码的最大容错率为30%,所以建议ratio的范围小于0.3 + * @return */ - private static Bitmap addLogo(Bitmap src, Bitmap logo) { + private static Bitmap addLogo(Bitmap src, Bitmap logo,@FloatRange(from = 0.0f,to = 1.0f) float ratio) { if (src == null) { return null; } @@ -154,8 +172,8 @@ public class CodeUtils { return src; } - //logo大小为二维码整体大小的1/6 - float scaleFactor = srcWidth * 1.0f / 6 / logoWidth; + //logo大小为二维码整体大小 + float scaleFactor = srcWidth * ratio / logoWidth; Bitmap bitmap = Bitmap.createBitmap(srcWidth, srcHeight, Bitmap.Config.ARGB_8888); try { Canvas canvas = new Canvas(bitmap); @@ -256,7 +274,7 @@ public class CodeUtils { BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); try { result = reader.decodeWithState(bitmap); - } catch (Exception e) {//解析失败则通过GlobalHistogramBinarizer 再试一次 + } catch (Exception e) {//解析失败时则通过GlobalHistogramBinarizer 再试一次 BinaryBitmap bitmap1 = new BinaryBitmap(new GlobalHistogramBinarizer(source)); try { result = reader.decodeWithState(bitmap1); @@ -291,7 +309,7 @@ public class CodeUtils { int h = newOpts.outHeight; float width = 800f; float height = 480f; - // 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可 + // 缩放比,由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可 int be = 1;// be=1表示不缩放 if (w > h && w > width) {// 如果宽度大的话根据宽度固定大小缩放 be = (int) (newOpts.outWidth / width); diff --git a/lib/src/main/res/drawable-xxhdpi/zxl_torch_off.png b/lib/src/main/res/drawable-xxhdpi/zxl_torch_off.png new file mode 100644 index 0000000..0aa92fe Binary files /dev/null and b/lib/src/main/res/drawable-xxhdpi/zxl_torch_off.png differ diff --git a/lib/src/main/res/drawable-xxhdpi/zxl_torch_on.png b/lib/src/main/res/drawable-xxhdpi/zxl_torch_on.png new file mode 100644 index 0000000..bc321fe Binary files /dev/null and b/lib/src/main/res/drawable-xxhdpi/zxl_torch_on.png differ diff --git a/lib/src/main/res/drawable/zxl_torch_selector.xml b/lib/src/main/res/drawable/zxl_torch_selector.xml new file mode 100644 index 0000000..b360cc4 --- /dev/null +++ b/lib/src/main/res/drawable/zxl_torch_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/lib/src/main/res/layout/zxl_capture.xml b/lib/src/main/res/layout/zxl_capture.xml index faab215..96ce59c 100644 --- a/lib/src/main/res/layout/zxl_capture.xml +++ b/lib/src/main/res/layout/zxl_capture.xml @@ -23,5 +23,11 @@ android:id="@+id/viewfinderView" android:layout_width="match_parent" android:layout_height="match_parent"/> - + \ No newline at end of file diff --git a/lib/src/main/res/values-v19/styles.xml b/lib/src/main/res/values-v19/styles.xml new file mode 100644 index 0000000..8b9ced6 --- /dev/null +++ b/lib/src/main/res/values-v19/styles.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/lib/src/main/res/values-v21/styles.xml b/lib/src/main/res/values-v21/styles.xml new file mode 100644 index 0000000..e04b29e --- /dev/null +++ b/lib/src/main/res/values-v21/styles.xml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/lib/src/main/res/values/colors.xml b/lib/src/main/res/values/colors.xml index 128abf9..384529a 100644 --- a/lib/src/main/res/values/colors.xml +++ b/lib/src/main/res/values/colors.xml @@ -8,4 +8,7 @@ #C0FFBD21 #FFC0C0C0 + #00000000 + #00000000 + \ No newline at end of file diff --git a/lib/src/main/res/values/dimens.xml b/lib/src/main/res/values/dimens.xml new file mode 100644 index 0000000..efcd3d5 --- /dev/null +++ b/lib/src/main/res/values/dimens.xml @@ -0,0 +1,4 @@ + + + 80dp + \ No newline at end of file diff --git a/lib/src/main/res/values/styles.xml b/lib/src/main/res/values/styles.xml new file mode 100644 index 0000000..f02107f --- /dev/null +++ b/lib/src/main/res/values/styles.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/versions.gradle b/versions.gradle index 01618b7..36a7f6e 100644 --- a/versions.gradle +++ b/versions.gradle @@ -1,7 +1,7 @@ //App def app_version = [:] -app_version.versionCode = 14 -app_version.versionName = "1.1.3-androidx" +app_version.versionCode = 16 +app_version.versionName = "1.1.4-androidx" ext.app_version = app_version //build version