diff --git a/README.md b/README.md index 5dd0f14..4795f45 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ ZXingLite for Android 是ZXing的精简版,基于ZXing库优化扫码和生成二维码/条形码功能,扫码界面完全支持自定义,也可一行代码使用默认实现的扫码功能。总之你想要的都在这里。 >简单如斯,你不试试? Come on~ + ### [AndroidX version](https://github.com/jenly1314/ZXingLite/tree/androidx) ## Gif 展示 @@ -55,21 +56,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 - + ``` @@ -86,17 +87,20 @@ allprojects { ## 引入的库: ```gradle //AndroidX -compileOnly 'androidx.appcompat:appcompat:1.0.0+' +api 'androidx.appcompat:appcompat:1.0.0+' api 'com.google.zxing:core:3.3.3' //Android -compileOnly 'com.android.support:appcompat-v7:28.0.0' +api 'com.android.support:appcompat-v7:28.0.0' 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 //跳转的默认扫码界面 @@ -129,7 +145,8 @@ api 'com.google.zxing:core:3.3.3' ```Xml + android:screenOrientation="portrait" + android:theme="@style/CaptureTheme"/> ``` ### 快速实现扫码有以下几种方式: @@ -147,6 +164,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 * 支持真实识别区域比例和识别区域偏移量可配置 * 对外暴露更多可配置参数 @@ -218,4 +239,4 @@ api 'com.google.zxing:core:3.3.3' - + diff --git a/app/release/app-release.apk b/app/release/app-release.apk index 4dcda69..555d09f 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 a1a4bfe..a5a5f53 100644 --- a/app/release/output.json +++ b/app/release/output.json @@ -1 +1 @@ -[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":13,"versionName":"1.1.3","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":15,"versionName":"1.1.4","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..5bf09ee 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -14,7 +14,7 @@ android:supportsRtl="true" android:theme="@style/AppTheme"> + android:screenOrientation="portrait"> @@ -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(); + } /** @@ -68,13 +73,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: @@ -82,4 +92,4 @@ public class CodeActivity extends AppCompatActivity { break; } } -} +} \ No newline at end of file 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 d56082f..7b4209f 100644 --- a/app/src/main/java/com/king/zxing/app/CustomActivity.java +++ b/app/src/main/java/com/king/zxing/app/CustomActivity.java @@ -32,6 +32,8 @@ public class CustomActivity extends AppCompatActivity implements OnCaptureCallba private ViewfinderView viewfinderView; + private View ivTorch; + @Override public void onCreate(Bundle icicle) { @@ -51,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) @@ -88,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); - } - /** * 扫码结果回调 @@ -123,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; } } -} +} \ No newline at end of file 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 20eedd2..95258bb 100644 --- a/app/src/main/java/com/king/zxing/app/CustomCaptureActivity.java +++ b/app/src/main/java/com/king/zxing/app/CustomCaptureActivity.java @@ -27,6 +27,7 @@ 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; /** * 自定义继承CaptureActivity @@ -34,8 +35,6 @@ import com.king.zxing.camera.CameraConfigurationUtils; */ public class CustomCaptureActivity extends CaptureActivity { - private ImageView ivFlash; - private boolean isContinuousScan; @Override public int getLayoutId() { @@ -51,12 +50,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)//播放音效 @@ -66,28 +59,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); - } /** * 扫码结果回调 @@ -103,21 +80,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 0d53511..2e89b1a 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; @@ -243,4 +243,4 @@ public class MainActivity extends AppCompatActivity implements EasyPermissions.P } } -} +} \ No newline at end of file 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 b103ccb..04555b3 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 @@ -32,9 +32,13 @@ import com.king.zxing.app.R; /** * @author Jenly Jenly */ -public class StatusBarUtils { +public final class StatusBarUtils { - public static void immersiveStatusBar(Activity activity,Toolbar toolbar) { + private StatusBarUtils(){ + throw new AssertionError(); + } + + public static void immersiveStatusBar(Activity activity, Toolbar toolbar) { immersiveStatusBar(activity,toolbar,0.0f); } @@ -78,7 +82,7 @@ public class StatusBarUtils { } /** 获取状态栏高度 */ - private static int getStatusBarHeight(Context context) { + public static int getStatusBarHeight(Context context) { return context.getResources().getDimensionPixelSize(R.dimen.status_bar_height); } } 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..a4ce7f7 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) { @@ -66,4 +68,4 @@ public enum UriUtils { return path; } -} +} \ No newline at end of file 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 1b5beea..1031719 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 7ccd472..3bc74e2 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/build.gradle b/lib/build.gradle index be23fad..491fc28 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -42,6 +42,6 @@ dependencies { androidTestImplementation deps.test.runner androidTestImplementation deps.test.espresso - compileOnly deps.support.appcompat + api deps.support.appcompat api deps.zxing } 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 6dc8c8a..c361870 100644 --- a/lib/src/main/java/com/king/zxing/CaptureActivity.java +++ b/lib/src/main/java/com/king/zxing/CaptureActivity.java @@ -21,6 +21,7 @@ import android.support.annotation.LayoutRes; import android.support.annotation.Nullable; import android.view.MotionEvent; import android.view.SurfaceView; +import android.view.View; import com.king.zxing.camera.CameraManager; @@ -31,6 +32,7 @@ public class CaptureActivity extends Activity implements OnCaptureCallback{ private SurfaceView surfaceView; private ViewfinderView viewfinderView; + private View ivTorch; private CaptureHelper mCaptureHelper; @@ -50,7 +52,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(); } @@ -73,7 +80,7 @@ public class CaptureActivity extends Activity implements OnCaptureCallback{ } /** - * {@link ViewfinderView} 的 id + * {@link #viewfinderView} 的 ID * @return */ public int getViewfinderViewId(){ @@ -82,13 +89,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 87b5363..9b9d09f 100644 --- a/lib/src/main/java/com/king/zxing/CaptureFragment.java +++ b/lib/src/main/java/com/king/zxing/CaptureFragment.java @@ -37,13 +37,14 @@ public class CaptureFragment extends Fragment implements OnCaptureCallback { private SurfaceView surfaceView; private ViewfinderView viewfinderView; + private View ivTorch; private CaptureHelper mCaptureHelper; public static CaptureFragment newInstance() { Bundle args = new Bundle(); - + CaptureFragment fragment = new CaptureFragment(); fragment.setArguments(args); return fragment; @@ -66,7 +67,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); } @@ -95,7 +101,6 @@ public class CaptureFragment extends Fragment implements OnCaptureCallback { return R.id.viewfinderView; } - /** * 预览界面{@link #surfaceView} 的id * @return @@ -104,6 +109,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} @@ -167,4 +180,4 @@ public class CaptureFragment extends Fragment implements OnCaptureCallback { return false; } -} +} \ No newline at end of file diff --git a/lib/src/main/java/com/king/zxing/CaptureHelper.java b/lib/src/main/java/com/king/zxing/CaptureHelper.java index 3e2e4aa..07e9364 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; @@ -26,11 +27,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; @@ -61,6 +64,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; @@ -126,21 +130,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; - } @@ -155,6 +196,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) { @@ -186,6 +243,11 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture //设置是否播放音效和震动 beepManager.setPlayBeep(isPlayBeep); beepManager.setVibrate(isVibrate); + + //设置闪光灯的太暗时和足够亮时的照度值 + ambientLightManager.setTooDarkLux(tooDarkLux); + ambientLightManager.setBrightEnoughLux(brightEnoughLux); + } @@ -565,6 +627,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表示扫码就结果会返回扫码原图,相应的会增加性能消耗。 @@ -691,4 +796,4 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture public InactivityTimer getInactivityTimer() { return inactivityTimer; } -} +} \ No newline at end of file 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 119d244..e103576 100644 --- a/lib/src/main/java/com/king/zxing/camera/CameraManager.java +++ b/lib/src/main/java/com/king/zxing/camera/CameraManager.java @@ -72,6 +72,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); @@ -192,14 +197,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, @@ -376,4 +389,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 0f36898..580507e 100644 --- a/lib/src/main/java/com/king/zxing/util/CodeUtils.java +++ b/lib/src/main/java/com/king/zxing/util/CodeUtils.java @@ -21,6 +21,7 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.support.annotation.ColorInt; +import android.support.annotation.FloatRange; import android.support.annotation.NonNull; import android.text.TextPaint; import android.text.TextUtils; @@ -51,7 +52,7 @@ import java.util.Vector; /** * @author Jenly Jenly */ -public class CodeUtils { +public final class CodeUtils { private CodeUtils(){ throw new AssertionError(); @@ -59,8 +60,8 @@ public class CodeUtils { /** * 生成二维码 - * @param content - * @param heightPix + * @param content 二维码的内容 + * @param heightPix 二维码的高 * @return */ public static Bitmap createQRCode(String content, int heightPix) { @@ -68,13 +69,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"); @@ -82,18 +95,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 { // 图像数据转换,使用了矩阵转换 @@ -116,7 +130,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; @@ -129,8 +143,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; } @@ -153,8 +171,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); @@ -255,7 +273,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); @@ -290,7 +308,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); @@ -451,4 +469,4 @@ public class CodeUtils { return bitmap; } -} +} \ No newline at end of file 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 45676f2..f571e4b 100644 --- a/versions.gradle +++ b/versions.gradle @@ -1,7 +1,7 @@ //App def app_version = [:] -app_version.versionCode = 13 //androidx 14 -app_version.versionName = "1.1.3" +app_version.versionCode = 15 //androidx 16 +app_version.versionName = "1.1.4" ext.app_version = app_version //build version