1、新增CaptureFragment
2、将扫码相关逻辑与界面分离,ZXingLite使用更容易扩展。
This commit is contained in:
BIN
.idea/caches/build_file_checksums.ser
generated
BIN
.idea/caches/build_file_checksums.ser
generated
Binary file not shown.
34
README.md
34
README.md
@@ -45,17 +45,17 @@ ZXingLite for Android 是ZXing的精简版,基于ZXing库优化扫码和生成
|
||||
<dependency>
|
||||
<groupId>com.king.zxing</groupId>
|
||||
<artifactId>zxing-lite</artifactId>
|
||||
<version>1.0.7</version>
|
||||
<version>1.1.0</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
```
|
||||
### Gradle:
|
||||
```gradle
|
||||
implementation 'com.king.zxing:zxing-lite:1.0.7'
|
||||
implementation 'com.king.zxing:zxing-lite:1.1.0'
|
||||
```
|
||||
### Lvy:
|
||||
```lvy
|
||||
<dependency org='com.king.zxing' name='zxing-lite' rev='1.0.7'>
|
||||
<dependency org='com.king.zxing' name='zxing-lite' rev='1.1.0'>
|
||||
<artifact name='$AID' ext='pom'></artifact>
|
||||
</dependency>
|
||||
```
|
||||
@@ -79,16 +79,20 @@ api 'com.google.zxing:core:3.3.3'
|
||||
|
||||
布局示例 (可自定义布局,布局内至少要保证有SurfaceView和ViewfinderView,控件id可根据重写CaptureActivity 的 getPreviewViewId 和 getViewFinderViewId方法自定义)
|
||||
```Xml
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<SurfaceView
|
||||
android:id="@+id/preview_view"
|
||||
android:id="@+id/surfaceView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
<com.king.zxing.ViewfinderView
|
||||
android:id="@+id/viewfinder_view"
|
||||
android:id="@+id/viewfinderView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
</merge>
|
||||
|
||||
</FrameLayout>
|
||||
```
|
||||
|
||||
代码示例 (二维码/条形码)
|
||||
@@ -102,9 +106,25 @@ api 'com.google.zxing:core:3.3.3'
|
||||
CodeUtils.createBarCode(content, BarcodeFormat.CODE_128,800,200);
|
||||
```
|
||||
|
||||
### 快速实现扫码有以下几种方式:
|
||||
|
||||
> 1、直接使用CaptureActivity或者CaptureFragment。(纯洁的扫码,无任何添加剂)
|
||||
|
||||
> 2、通过继承CaptureActivity或者CaptureFragment并自定义布局。(适用于大多场景,并无需关心扫码相关逻辑)
|
||||
|
||||
> 3、在你项目的Activity或者Fragment中创建创建一个CaptureHelper并在相应的生命周期中调用CaptureHelper的周期。(适用于想在扫码界面写交互逻辑,又因为项目架构或其它原因,无法直接或间接继承CaptureActivity或CaptureFragment时使用)
|
||||
|
||||
> 4、参照CaptureHelper写一个自定义的扫码帮助类,其它步骤同方式3。(扩展高级用法,谨慎使用)
|
||||
|
||||
|
||||
更多使用详情,请查看[app](app)中的源码使用示例
|
||||
|
||||
## 版本记录
|
||||
|
||||
#### v1.1.0:2019-4-19
|
||||
* 将扫码相关逻辑与界面分离,ZXingLite使用更容易扩展。
|
||||
* 新增CaptureFragment
|
||||
|
||||
#### v1.0.7:2019-4-9
|
||||
* 新增网格样式的扫描激光(类似支付宝扫码样式)
|
||||
* 升级Gradle至v4.6
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":8,"versionName":"1.0.7","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]
|
||||
[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":9,"versionName":"1.1.0","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]
|
||||
@@ -21,12 +21,25 @@
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name="com.king.zxing.CaptureActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
|
||||
<activity
|
||||
android:name=".EasyCaptureActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
<activity
|
||||
android:name=".CustomCaptureActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
|
||||
<activity
|
||||
android:name=".CaptureFragmentActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
|
||||
<activity
|
||||
android:name=".CustomActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
|
||||
<activity
|
||||
android:name=".CodeActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.king.zxing.app;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.IdRes;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.king.zxing.CaptureFragment;
|
||||
import com.king.zxing.app.util.StatusBarUtils;
|
||||
|
||||
/**
|
||||
* Fragment扫码
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class CaptureFragmentActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.fragment_activity);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
StatusBarUtils.immersiveStatusBar(this,toolbar,0.2f);
|
||||
TextView tvTitle = findViewById(R.id.tvTitle);
|
||||
tvTitle.setText(getIntent().getStringExtra(MainActivity.KEY_TITLE));
|
||||
|
||||
replaceFragment(CaptureFragment.newInstance());
|
||||
}
|
||||
|
||||
public void replaceFragment(Fragment fragment){
|
||||
replaceFragment( R.id.fragmentContent,fragment);
|
||||
}
|
||||
|
||||
public void replaceFragment(@IdRes int id, Fragment fragment) {
|
||||
getSupportFragmentManager().beginTransaction().replace(id, fragment).commit();
|
||||
}
|
||||
}
|
||||
143
app/src/main/java/com/king/zxing/app/CustomActivity.java
Normal file
143
app/src/main/java/com/king/zxing/app/CustomActivity.java
Normal file
@@ -0,0 +1,143 @@
|
||||
package com.king.zxing.app;
|
||||
|
||||
import android.hardware.Camera;
|
||||
import android.os.Bundle;
|
||||
import android.app.Activity;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.king.zxing.CaptureHelper;
|
||||
import com.king.zxing.OnCaptureCallback;
|
||||
import com.king.zxing.ViewfinderView;
|
||||
import com.king.zxing.app.util.StatusBarUtils;
|
||||
|
||||
/**
|
||||
* 自定义扫码:当直接使用CaptureActivity
|
||||
* 自定义扫码,切记自定义扫码需在{@link Activity}或者{@link Fragment}相对应的生命周期里面调用{@link #mCaptureHelper}对应的生命周期
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class CustomActivity extends AppCompatActivity implements OnCaptureCallback {
|
||||
|
||||
private boolean isContinuousScan;
|
||||
|
||||
private CaptureHelper mCaptureHelper;
|
||||
|
||||
private SurfaceView surfaceView;
|
||||
|
||||
private ViewfinderView viewfinderView;
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
setContentView(R.layout.custom_activity);
|
||||
|
||||
initUI();
|
||||
}
|
||||
|
||||
private void initUI(){
|
||||
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
StatusBarUtils.immersiveStatusBar(this,toolbar,0.2f);
|
||||
TextView tvTitle = findViewById(R.id.tvTitle);
|
||||
tvTitle.setText(getIntent().getStringExtra(MainActivity.KEY_TITLE));
|
||||
|
||||
|
||||
surfaceView = findViewById(R.id.surfaceView);
|
||||
viewfinderView = findViewById(R.id.viewfinderView);
|
||||
|
||||
isContinuousScan = getIntent().getBooleanExtra(MainActivity.KEY_IS_CONTINUOUS,false);
|
||||
|
||||
mCaptureHelper = new CaptureHelper(this,surfaceView,viewfinderView);
|
||||
mCaptureHelper.onCreate();
|
||||
mCaptureHelper.vibrate(true)
|
||||
.continuousScan(isContinuousScan);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mCaptureHelper.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mCaptureHelper.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mCaptureHelper.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
mCaptureHelper.onTouchEvent(event);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 扫码结果回调
|
||||
* @param result 扫码结果
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean onResultCallback(String result) {
|
||||
if(isContinuousScan){
|
||||
Toast.makeText(this,result,Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import com.king.zxing.CaptureActivity;
|
||||
import com.king.zxing.app.util.StatusBarUtils;
|
||||
|
||||
/**
|
||||
* 自定义继承CaptureActivity
|
||||
* @author Jenly <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class CustomCaptureActivity extends CaptureActivity {
|
||||
@@ -46,9 +47,10 @@ public class CustomCaptureActivity extends CaptureActivity {
|
||||
tvTitle.setText(getIntent().getStringExtra(MainActivity.KEY_TITLE));
|
||||
|
||||
isContinuousScan = getIntent().getBooleanExtra(MainActivity.KEY_IS_CONTINUOUS,false);
|
||||
|
||||
getBeepManager().setPlayBeep(true);
|
||||
getBeepManager().setVibrate(true);
|
||||
//获取CaptureHelper,里面有扫码相关的配置设置
|
||||
getCaptureHelper().playBeep(true)//播放音效
|
||||
.vibrate(true)//震动
|
||||
.continuousScan(isContinuousScan);//是否连扫
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,37 +73,21 @@ public class CustomCaptureActivity extends CaptureActivity {
|
||||
camera.setParameters(parameters);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 接收扫码结果,想支持连扫时,可将{@link #isContinuousScan()}返回为{@code true}并重写此方法
|
||||
* 如果{@link #isContinuousScan()}支持连扫,则默认重启扫码和解码器;当连扫逻辑太复杂时,
|
||||
* 请将{@link #isAutoRestartPreviewAndDecode()}返回为{@code false},并手动调用{@link #restartPreviewAndDecode()}
|
||||
* 扫码结果回调
|
||||
* @param result 扫码结果
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public void onResult(Result result) {
|
||||
super.onResult(result);
|
||||
public boolean onResultCallback(String result) {
|
||||
if(isContinuousScan){//连续扫码时,直接弹出结果
|
||||
Toast.makeText(this,result.getText(),Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(this,result,Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
return super.onResultCallback(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否连续扫码,如果想支持连续扫码,则将此方法返回{@code true}并重写{@link #onResult(Result)}
|
||||
* @return 默认返回 false
|
||||
*/
|
||||
@Override
|
||||
public boolean isContinuousScan() {
|
||||
return isContinuousScan;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否自动重启扫码和解码器,当支持连扫时才起作用。
|
||||
* @return 默认返回 true
|
||||
*/
|
||||
@Override
|
||||
public boolean isAutoRestartPreviewAndDecode() {
|
||||
return super.isAutoRestartPreviewAndDecode();
|
||||
}
|
||||
|
||||
private void clickFlash(View v){
|
||||
if(v.isSelected()){
|
||||
|
||||
@@ -18,7 +18,6 @@ package com.king.zxing.app;
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.provider.MediaStore;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.app.ActivityOptionsCompat;
|
||||
@@ -30,8 +29,6 @@ import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.zxing.DecodeHintType;
|
||||
import com.google.zxing.common.StringUtils;
|
||||
import com.king.zxing.CaptureActivity;
|
||||
import com.king.zxing.Intents;
|
||||
import com.king.zxing.app.util.UriUtils;
|
||||
@@ -42,6 +39,20 @@ import java.util.List;
|
||||
import pub.devrel.easypermissions.AfterPermissionGranted;
|
||||
import pub.devrel.easypermissions.EasyPermissions;
|
||||
|
||||
/**
|
||||
* 扫码Demo示例说明
|
||||
*
|
||||
* 快速实现扫码有以下几种方式:
|
||||
*
|
||||
* 1、直接使用CaptureActivity或者CaptureFragment。(纯洁的扫码,无任何添加剂)
|
||||
*
|
||||
* 2、通过继承CaptureActivity或者CaptureFragment并自定义布局。(适用于大多场景,并无需关心扫码相关逻辑)
|
||||
*
|
||||
* 3、在你项目的Activity或者Fragment中创建创建一个CaptureHelper并在相应的生命周期中调用CaptureHelper的周期。(适用于想在扫码界面写交互逻辑,又因为项目架构或其它原因,无法直接或间接继承CaptureActivity或CaptureFragment时使用)
|
||||
*
|
||||
* 4、参照CaptureHelper写一个自定义的扫码帮助类,其它步骤同方式3。(扩展高级用法,谨慎使用)
|
||||
*
|
||||
*/
|
||||
public class MainActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks{
|
||||
|
||||
public static final String KEY_TITLE = "key_title";
|
||||
@@ -195,18 +206,18 @@ public class MainActivity extends AppCompatActivity implements EasyPermissions.P
|
||||
isContinuousScan = false;
|
||||
switch (v.getId()){
|
||||
case R.id.btn0:
|
||||
this.cls = CaptureActivity.class;
|
||||
this.title = ((Button)v).getText().toString();
|
||||
checkCameraPermissions();
|
||||
break;
|
||||
case R.id.btn1:
|
||||
this.cls = CustomCaptureActivity.class;
|
||||
this.title = ((Button)v).getText().toString();
|
||||
isContinuousScan = true;
|
||||
checkCameraPermissions();
|
||||
break;
|
||||
case R.id.btn1:
|
||||
this.cls = CaptureActivity.class;
|
||||
this.title = ((Button)v).getText().toString();
|
||||
checkCameraPermissions();
|
||||
break;
|
||||
case R.id.btn2:
|
||||
this.cls = EasyCaptureActivity.class;
|
||||
this.cls = CaptureFragmentActivity.class;
|
||||
this.title = ((Button)v).getText().toString();
|
||||
checkCameraPermissions();
|
||||
break;
|
||||
@@ -216,12 +227,17 @@ public class MainActivity extends AppCompatActivity implements EasyPermissions.P
|
||||
checkCameraPermissions();
|
||||
break;
|
||||
case R.id.btn4:
|
||||
startCode(false);
|
||||
this.cls = CustomActivity.class;
|
||||
this.title = ((Button)v).getText().toString();
|
||||
checkCameraPermissions();
|
||||
break;
|
||||
case R.id.btn5:
|
||||
startCode(true);
|
||||
startCode(false);
|
||||
break;
|
||||
case R.id.btn6:
|
||||
startCode(true);
|
||||
break;
|
||||
case R.id.btn7:
|
||||
checkExternalStoragePermissions();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -26,13 +26,6 @@
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:text="@string/app_name"/>
|
||||
</android.support.v7.widget.Toolbar>
|
||||
<android.support.constraint.Guideline
|
||||
android:id="@+id/line"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@+id/toolbar"
|
||||
app:layout_constraintGuide_percent="0.2"/>
|
||||
<Button
|
||||
android:id="@+id/btn0"
|
||||
android:layout_width="match_parent"
|
||||
@@ -41,10 +34,10 @@
|
||||
android:layout_marginRight="20dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:text="连续扫码"
|
||||
android:text="默认扫码"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/line"
|
||||
app:layout_constraintTop_toBottomOf="@+id/toolbar"
|
||||
style="@style/OnClick"/>
|
||||
<Button
|
||||
android:id="@+id/btn1"
|
||||
@@ -54,7 +47,7 @@
|
||||
android:layout_marginRight="20dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:text="默认扫码"
|
||||
android:text="连续扫码"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/btn0"
|
||||
@@ -67,7 +60,8 @@
|
||||
android:layout_marginRight="20dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:text="简单自定义布局扫码"
|
||||
android:text="Fragment扫码"
|
||||
android:textAllCaps="false"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/btn1"
|
||||
@@ -93,7 +87,7 @@
|
||||
android:layout_marginRight="20dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:text="生成条形码"
|
||||
android:text="自定义扫码"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/btn3"
|
||||
@@ -106,7 +100,7 @@
|
||||
android:layout_marginRight="20dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:text="生成二维码"
|
||||
android:text="生成条形码"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/btn4"
|
||||
@@ -119,9 +113,22 @@
|
||||
android:layout_marginRight="20dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:text="识别一维码/二维码图片"
|
||||
android:text="生成二维码"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/btn5"
|
||||
style="@style/OnClick"/>
|
||||
<Button
|
||||
android:id="@+id/btn7"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginRight="20dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:text="识别一维码/二维码图片"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/btn6"
|
||||
style="@style/OnClick"/>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
37
app/src/main/res/layout/custom_activity.xml
Normal file
37
app/src/main/res/layout/custom_activity.xml
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<SurfaceView
|
||||
android:id="@+id/surfaceView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
<com.king.zxing.ViewfinderView
|
||||
android:id="@+id/viewfinderView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:labelText="@string/tips_scan_code"
|
||||
app:labelTextSize="@dimen/size_14sp"
|
||||
app:laserColor="@color/colorAccent"
|
||||
app:frameColor="@color/colorPrimary"
|
||||
app:cornerColor="@color/colorPrimary"
|
||||
app:resultPointColor="@color/colorAccent"
|
||||
app:labelTextLocation="bottom"
|
||||
app:laserStyle="grid"
|
||||
app:gridHeight="0dp"/>
|
||||
<ImageView
|
||||
android:id="@+id/ivFlash"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/flash_selected_selector"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginTop="160dp"
|
||||
style="@style/OnClick"/>
|
||||
<include layout="@layout/toolbar_capture"/>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
@@ -6,11 +6,11 @@
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<SurfaceView
|
||||
android:id="@+id/preview_view"
|
||||
android:id="@+id/surfaceView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
<com.king.zxing.ViewfinderView
|
||||
android:id="@+id/viewfinder_view"
|
||||
android:id="@+id/viewfinderView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:labelText="@string/tips_scan_code"
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<include layout="@layout/capture"/>
|
||||
<include layout="@layout/zxl_capture"/>
|
||||
<include layout="@layout/toolbar_capture"/>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
12
app/src/main/res/layout/fragment_activity.xml
Normal file
12
app/src/main/res/layout/fragment_activity.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<LinearLayout
|
||||
android:id="@+id/fragmentContent"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
<include layout="@layout/toolbar_capture"/>
|
||||
</FrameLayout>
|
||||
@@ -2,7 +2,7 @@
|
||||
<string name="app_name">ZXingLite</string>
|
||||
<string name="permission_camera">App扫码需要用到拍摄权限</string>
|
||||
<string name="permission_external_storage">App需要用到读写权限</string>
|
||||
<string name="tips_scan_code">将二维码/条形码放入框内,即可自动扫码</string>
|
||||
<string name="tips_scan_code">将二维码/条形码放入框内,即可自动扫描</string>
|
||||
<string name="qr_code">二维码</string>
|
||||
<string name="bar_code">条形码</string>
|
||||
</resources>
|
||||
|
||||
@@ -5,14 +5,10 @@
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
<uses-permission android:name="android.permission.FLASHLIGHT"/>
|
||||
<!-- unavailable in API 23 -->
|
||||
<uses-permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"/>
|
||||
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
|
||||
|
||||
<application>
|
||||
<activity
|
||||
android:name="com.king.zxing.CaptureActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
@@ -32,7 +32,7 @@ import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Manages beeps and vibrations for {@link CaptureActivity}.
|
||||
* Manages beeps and vibrations for {@link Activity}.
|
||||
*/
|
||||
public final class BeepManager implements MediaPlayer.OnErrorListener, Closeable {
|
||||
|
||||
@@ -62,7 +62,7 @@ public final class BeepManager implements MediaPlayer.OnErrorListener, Closeable
|
||||
|
||||
synchronized void updatePrefs() {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||
playBeep = shouldBeep(prefs, 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,
|
||||
@@ -83,7 +83,7 @@ public final class BeepManager implements MediaPlayer.OnErrorListener, Closeable
|
||||
}
|
||||
|
||||
private static boolean shouldBeep(SharedPreferences prefs, Context activity) {
|
||||
boolean shouldPlayBeep = prefs.getBoolean(Preferences.KEY_PLAY_BEEP, true);
|
||||
boolean shouldPlayBeep = prefs.getBoolean(Preferences.KEY_PLAY_BEEP, false);
|
||||
if (shouldPlayBeep) {
|
||||
// See if sound settings overrides this
|
||||
AudioManager audioService = (AudioManager) activity.getSystemService(Context.AUDIO_SERVICE);
|
||||
@@ -97,7 +97,7 @@ public final class BeepManager implements MediaPlayer.OnErrorListener, Closeable
|
||||
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||
private MediaPlayer buildMediaPlayer(Context activity) {
|
||||
MediaPlayer mediaPlayer = new MediaPlayer();
|
||||
try (AssetFileDescriptor file = activity.getResources().openRawResourceFd(R.raw.beep)) {
|
||||
try (AssetFileDescriptor file = activity.getResources().openRawResourceFd(R.raw.zxl_beep)) {
|
||||
mediaPlayer.setDataSource(file.getFileDescriptor(), file.getStartOffset(), file.getLength());
|
||||
mediaPlayer.setOnErrorListener(this);
|
||||
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
170
lib/src/main/java/com/king/zxing/CaptureFragment.java
Normal file
170
lib/src/main/java/com/king/zxing/CaptureFragment.java
Normal file
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Jenly Yu
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.king.zxing;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.LayoutRes;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.king.zxing.camera.CameraManager;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class CaptureFragment extends Fragment implements OnCaptureCallback {
|
||||
|
||||
public static final String KEY_RESULT = Intents.Scan.RESULT;
|
||||
|
||||
private View mRootView;
|
||||
|
||||
private SurfaceView surfaceView;
|
||||
private ViewfinderView viewfinderView;
|
||||
|
||||
private CaptureHelper mCaptureHelper;
|
||||
|
||||
public static CaptureFragment newInstance() {
|
||||
|
||||
Bundle args = new Bundle();
|
||||
|
||||
CaptureFragment fragment = new CaptureFragment();
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
int layoutId = getLayoutId();
|
||||
if(isContentView(layoutId)){
|
||||
mRootView = inflater.inflate(getLayoutId(),container,false);
|
||||
}
|
||||
initUI();
|
||||
return mRootView;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
public void initUI(){
|
||||
surfaceView = mRootView.findViewById(getSurfaceViewId());
|
||||
viewfinderView = mRootView.findViewById(getViewfinderViewId());
|
||||
mCaptureHelper = new CaptureHelper(this,surfaceView,viewfinderView);
|
||||
mCaptureHelper.setOnCaptureCallback(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回true时会自动初始化{@link #mRootView},返回为false时需自己去通过{@link #setRootView(View)}初始化{@link #mRootView}
|
||||
* @param layoutId
|
||||
* @return 默认返回true
|
||||
*/
|
||||
public boolean isContentView(@LayoutRes int layoutId){
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 布局id
|
||||
* @return
|
||||
*/
|
||||
public int getLayoutId(){
|
||||
return R.layout.zxl_capture;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ViewfinderView} 的 id
|
||||
* @return
|
||||
*/
|
||||
public int getViewfinderViewId(){
|
||||
return R.id.viewfinderView;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 预览界面{@link #surfaceView} 的id
|
||||
* @return
|
||||
*/
|
||||
public int getSurfaceViewId(){
|
||||
return R.id.surfaceView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get {@link CaptureHelper}
|
||||
* @return {@link #mCaptureHelper}
|
||||
*/
|
||||
public CaptureHelper getCaptureHelper(){
|
||||
return mCaptureHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get {@link CameraManager}
|
||||
* @return {@link #mCaptureHelper#getCameraManager()}
|
||||
*/
|
||||
public CameraManager getCameraManager(){
|
||||
return mCaptureHelper.getCameraManager();
|
||||
}
|
||||
|
||||
//--------------------------------------------
|
||||
|
||||
public View getRootView() {
|
||||
return mRootView;
|
||||
}
|
||||
|
||||
public void setRootView(View rootView) {
|
||||
this.mRootView = rootView;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
mCaptureHelper.onCreate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mCaptureHelper.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mCaptureHelper.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mCaptureHelper.onDestroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收扫码结果回调
|
||||
* @param result 扫码结果
|
||||
* @return 返回true表示拦截,将不自动执行后续逻辑,为false表示不拦截,默认不拦截
|
||||
*/
|
||||
@Override
|
||||
public boolean onResultCallback(String result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,169 +1,154 @@
|
||||
package com.king.zxing;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2008 ZXing authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.provider.Browser;
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.DecodeHintType;
|
||||
import com.google.zxing.Result;
|
||||
import com.king.zxing.camera.CameraManager;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This class handles all the messaging which comprises the state machine for capture.
|
||||
*
|
||||
* @author dswitkin@google.com (Daniel Switkin)
|
||||
*/
|
||||
public final class CaptureActivityHandler extends Handler {
|
||||
|
||||
private static final String TAG = CaptureActivityHandler.class.getSimpleName();
|
||||
|
||||
private final CaptureActivity activity;
|
||||
private final DecodeThread decodeThread;
|
||||
private State state;
|
||||
private final CameraManager cameraManager;
|
||||
|
||||
private enum State {
|
||||
PREVIEW,
|
||||
SUCCESS,
|
||||
DONE
|
||||
}
|
||||
|
||||
CaptureActivityHandler(CaptureActivity activity,
|
||||
Collection<BarcodeFormat> decodeFormats,
|
||||
Map<DecodeHintType,?> baseHints,
|
||||
String characterSet,
|
||||
CameraManager cameraManager) {
|
||||
this.activity = activity;
|
||||
decodeThread = new DecodeThread(activity, decodeFormats, baseHints, characterSet,
|
||||
new ViewfinderResultPointCallback(activity.getViewfinderView()));
|
||||
decodeThread.start();
|
||||
state = State.SUCCESS;
|
||||
|
||||
// Start ourselves capturing previews and decoding.
|
||||
this.cameraManager = cameraManager;
|
||||
cameraManager.startPreview();
|
||||
restartPreviewAndDecode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message message) {
|
||||
if (message.what == R.id.restart_preview) {
|
||||
restartPreviewAndDecode();
|
||||
|
||||
} else if (message.what == R.id.decode_succeeded) {
|
||||
state = State.SUCCESS;
|
||||
Bundle bundle = message.getData();
|
||||
Bitmap barcode = null;
|
||||
float scaleFactor = 1.0f;
|
||||
if (bundle != null) {
|
||||
byte[] compressedBitmap = bundle.getByteArray(DecodeThread.BARCODE_BITMAP);
|
||||
if (compressedBitmap != null) {
|
||||
barcode = BitmapFactory.decodeByteArray(compressedBitmap, 0, compressedBitmap.length, null);
|
||||
// Mutable copy:
|
||||
barcode = barcode.copy(Bitmap.Config.ARGB_8888, true);
|
||||
}
|
||||
scaleFactor = bundle.getFloat(DecodeThread.BARCODE_SCALED_FACTOR);
|
||||
}
|
||||
activity.handleDecode((Result) message.obj, barcode, scaleFactor);
|
||||
|
||||
} else if (message.what == R.id.decode_failed) {// We're decoding as fast as possible, so when one decode fails, start another.
|
||||
state = State.PREVIEW;
|
||||
cameraManager.requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
|
||||
|
||||
} else if (message.what == R.id.return_scan_result) {
|
||||
activity.setResult(Activity.RESULT_OK, (Intent) message.obj);
|
||||
activity.finish();
|
||||
|
||||
} else if (message.what == R.id.launch_product_query) {
|
||||
String url = (String) message.obj;
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.addFlags(Intents.FLAG_NEW_DOC);
|
||||
intent.setData(Uri.parse(url));
|
||||
|
||||
ResolveInfo resolveInfo =
|
||||
activity.getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
|
||||
String browserPackageName = null;
|
||||
if (resolveInfo != null && resolveInfo.activityInfo != null) {
|
||||
browserPackageName = resolveInfo.activityInfo.packageName;
|
||||
Log.d(TAG, "Using browser in package " + browserPackageName);
|
||||
}
|
||||
|
||||
// Needed for default Android browser / Chrome only apparently
|
||||
if (browserPackageName != null) {
|
||||
switch (browserPackageName) {
|
||||
case "com.android.browser":
|
||||
case "com.android.chrome":
|
||||
intent.setPackage(browserPackageName);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.putExtra(Browser.EXTRA_APPLICATION_ID, browserPackageName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
activity.startActivity(intent);
|
||||
} catch (ActivityNotFoundException ignored) {
|
||||
Log.w(TAG, "Can't find anything to handle VIEW of URI " + url);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void quitSynchronously() {
|
||||
state = State.DONE;
|
||||
cameraManager.stopPreview();
|
||||
Message quit = Message.obtain(decodeThread.getHandler(), R.id.quit);
|
||||
quit.sendToTarget();
|
||||
try {
|
||||
// Wait at most half a second; should be enough time, and onPause() will timeout quickly
|
||||
decodeThread.join(500L);
|
||||
} catch (InterruptedException e) {
|
||||
// continue
|
||||
}
|
||||
|
||||
// Be absolutely sure we don't send any queued up messages
|
||||
removeMessages(R.id.decode_succeeded);
|
||||
removeMessages(R.id.decode_failed);
|
||||
}
|
||||
|
||||
public void restartPreviewAndDecode() {
|
||||
if (state == State.SUCCESS) {
|
||||
state = State.PREVIEW;
|
||||
cameraManager.requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
|
||||
activity.drawViewfinder();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
package com.king.zxing;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.provider.Browser;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.DecodeHintType;
|
||||
import com.google.zxing.Result;
|
||||
import com.king.zxing.camera.CameraManager;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class CaptureHandler extends Handler {
|
||||
|
||||
private static final String TAG = CaptureHandler.class.getSimpleName();
|
||||
|
||||
private final OnCaptureListener onCaptureListener;
|
||||
private final DecodeThread decodeThread;
|
||||
private State state;
|
||||
private final CameraManager cameraManager;
|
||||
private final Activity activity;
|
||||
private final ViewfinderView viewfinderView;
|
||||
|
||||
|
||||
private enum State {
|
||||
PREVIEW,
|
||||
SUCCESS,
|
||||
DONE
|
||||
}
|
||||
|
||||
CaptureHandler(Activity activity,ViewfinderView viewfinderView,OnCaptureListener onCaptureListener,
|
||||
Collection<BarcodeFormat> decodeFormats,
|
||||
Map<DecodeHintType,?> baseHints,
|
||||
String characterSet,
|
||||
CameraManager cameraManager) {
|
||||
this.activity = activity;
|
||||
this.viewfinderView = viewfinderView;
|
||||
this.onCaptureListener = onCaptureListener;
|
||||
decodeThread = new DecodeThread(activity,cameraManager,this, decodeFormats, baseHints, characterSet,
|
||||
new ViewfinderResultPointCallback(viewfinderView));
|
||||
decodeThread.start();
|
||||
state = State.SUCCESS;
|
||||
|
||||
// Start ourselves capturing previews and decoding.
|
||||
this.cameraManager = cameraManager;
|
||||
cameraManager.startPreview();
|
||||
restartPreviewAndDecode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message message) {
|
||||
if (message.what == R.id.restart_preview) {
|
||||
restartPreviewAndDecode();
|
||||
|
||||
} else if (message.what == R.id.decode_succeeded) {
|
||||
state = State.SUCCESS;
|
||||
Bundle bundle = message.getData();
|
||||
Bitmap barcode = null;
|
||||
float scaleFactor = 1.0f;
|
||||
if (bundle != null) {
|
||||
byte[] compressedBitmap = bundle.getByteArray(DecodeThread.BARCODE_BITMAP);
|
||||
if (compressedBitmap != null) {
|
||||
barcode = BitmapFactory.decodeByteArray(compressedBitmap, 0, compressedBitmap.length, null);
|
||||
// Mutable copy:
|
||||
barcode = barcode.copy(Bitmap.Config.ARGB_8888, true);
|
||||
}
|
||||
scaleFactor = bundle.getFloat(DecodeThread.BARCODE_SCALED_FACTOR);
|
||||
}
|
||||
onCaptureListener.onHandleDecode((Result) message.obj, barcode, scaleFactor);
|
||||
|
||||
} else if (message.what == R.id.decode_failed) {// We're decoding as fast as possible, so when one decode fails, start another.
|
||||
state = State.PREVIEW;
|
||||
cameraManager.requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
|
||||
|
||||
} else if (message.what == R.id.return_scan_result) {
|
||||
activity.setResult(Activity.RESULT_OK, (Intent) message.obj);
|
||||
activity.finish();
|
||||
|
||||
} else if (message.what == R.id.launch_product_query) {
|
||||
String url = (String) message.obj;
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.addFlags(Intents.FLAG_NEW_DOC);
|
||||
intent.setData(Uri.parse(url));
|
||||
|
||||
ResolveInfo resolveInfo =
|
||||
activity.getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
|
||||
String browserPackageName = null;
|
||||
if (resolveInfo != null && resolveInfo.activityInfo != null) {
|
||||
browserPackageName = resolveInfo.activityInfo.packageName;
|
||||
Log.d(TAG, "Using browser in package " + browserPackageName);
|
||||
}
|
||||
|
||||
// Needed for default Android browser / Chrome only apparently
|
||||
if (browserPackageName != null) {
|
||||
switch (browserPackageName) {
|
||||
case "com.android.browser":
|
||||
case "com.android.chrome":
|
||||
intent.setPackage(browserPackageName);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.putExtra(Browser.EXTRA_APPLICATION_ID, browserPackageName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
activity.startActivity(intent);
|
||||
} catch (ActivityNotFoundException ignored) {
|
||||
Log.w(TAG, "Can't find anything to handle VIEW of URI " + url);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void quitSynchronously() {
|
||||
state = State.DONE;
|
||||
cameraManager.stopPreview();
|
||||
Message quit = Message.obtain(decodeThread.getHandler(), R.id.quit);
|
||||
quit.sendToTarget();
|
||||
try {
|
||||
// Wait at most half a second; should be enough time, and onPause() will timeout quickly
|
||||
decodeThread.join(500L);
|
||||
} catch (InterruptedException e) {
|
||||
// continue
|
||||
}
|
||||
|
||||
// Be absolutely sure we don't send any queued up messages
|
||||
removeMessages(R.id.decode_succeeded);
|
||||
removeMessages(R.id.decode_failed);
|
||||
}
|
||||
|
||||
public void restartPreviewAndDecode() {
|
||||
if (state == State.SUCCESS) {
|
||||
state = State.PREVIEW;
|
||||
cameraManager.requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
|
||||
viewfinderView.drawViewfinder();
|
||||
}
|
||||
}
|
||||
}
|
||||
522
lib/src/main/java/com/king/zxing/CaptureHelper.java
Normal file
522
lib/src/main/java/com/king/zxing/CaptureHelper.java
Normal file
@@ -0,0 +1,522 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Jenly Yu
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.king.zxing;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.hardware.Camera;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.DecodeHintType;
|
||||
import com.google.zxing.Result;
|
||||
import com.king.zxing.camera.CameraManager;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,CaptureManager {
|
||||
|
||||
public static final String TAG = CaptureHelper.class.getSimpleName();
|
||||
|
||||
private Activity activity;
|
||||
|
||||
private CaptureHandler captureHandler;
|
||||
private OnCaptureListener onCaptureListener;
|
||||
|
||||
private CameraManager cameraManager;
|
||||
|
||||
private InactivityTimer inactivityTimer;
|
||||
private BeepManager beepManager;
|
||||
private AmbientLightManager ambientLightManager;
|
||||
|
||||
|
||||
private ViewfinderView viewfinderView;
|
||||
private SurfaceHolder surfaceHolder;
|
||||
private SurfaceHolder.Callback callback;
|
||||
|
||||
private Collection<BarcodeFormat> decodeFormats;
|
||||
private Map<DecodeHintType,?> decodeHints;
|
||||
private String characterSet;
|
||||
|
||||
private boolean hasSurface;
|
||||
/**
|
||||
* 默认触控误差值
|
||||
*/
|
||||
private static final int DEVIATION = 6;
|
||||
/**
|
||||
* 是否支持缩放(变焦),默认支持
|
||||
*/
|
||||
private boolean isSupportZoom = true;
|
||||
private float oldDistance;
|
||||
/**
|
||||
* 是否支持连扫,默认不支持
|
||||
*/
|
||||
private boolean isContinuousScan = false;
|
||||
/**
|
||||
* 连扫时,是否自动重置预览和解码器,默认自动重置
|
||||
*/
|
||||
private boolean isAutoRestartPreviewAndDecode = true;
|
||||
/**
|
||||
* 是否播放音效
|
||||
*/
|
||||
private boolean isPlayBeep;
|
||||
/**
|
||||
* 是否震动
|
||||
*/
|
||||
private boolean isVibrate;
|
||||
|
||||
private OnCaptureCallback onCaptureCallback;
|
||||
|
||||
|
||||
public CaptureHelper(Fragment fragment, SurfaceView surfaceView, ViewfinderView viewfinderView){
|
||||
this(fragment.getActivity(),surfaceView,viewfinderView);
|
||||
|
||||
}
|
||||
|
||||
public CaptureHelper(Activity activity,SurfaceView surfaceView,ViewfinderView viewfinderView){
|
||||
this.activity = activity;
|
||||
this.viewfinderView = viewfinderView;
|
||||
surfaceHolder = surfaceView.getHolder();
|
||||
hasSurface = false;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(){
|
||||
inactivityTimer = new InactivityTimer(activity);
|
||||
beepManager = new BeepManager(activity);
|
||||
ambientLightManager = new AmbientLightManager(activity);
|
||||
|
||||
cameraManager = new CameraManager(activity);
|
||||
|
||||
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 = new OnCaptureListener() {
|
||||
|
||||
@Override
|
||||
public void onHandleDecode(Result result, Bitmap barcode, float scaleFactor) {
|
||||
inactivityTimer.onActivity();
|
||||
beepManager.playBeepSoundAndVibrate();
|
||||
|
||||
onResult(result);
|
||||
}
|
||||
|
||||
};
|
||||
//设置是否播放音效和震动
|
||||
beepManager.setPlayBeep(isPlayBeep);
|
||||
beepManager.setVibrate(isVibrate);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@link Activity#onResume()}
|
||||
*/
|
||||
@Override
|
||||
public void onResume(){
|
||||
beepManager.updatePrefs();
|
||||
ambientLightManager.start(cameraManager);
|
||||
|
||||
inactivityTimer.onResume();
|
||||
|
||||
surfaceHolder.addCallback(callback);
|
||||
|
||||
if (hasSurface) {
|
||||
initCamera(surfaceHolder);
|
||||
} else {
|
||||
surfaceHolder.addCallback(callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Activity#onPause()}
|
||||
*/
|
||||
@Override
|
||||
public void onPause(){
|
||||
if (captureHandler != null) {
|
||||
captureHandler.quitSynchronously();
|
||||
captureHandler = null;
|
||||
}
|
||||
inactivityTimer.onPause();
|
||||
ambientLightManager.stop();
|
||||
beepManager.close();
|
||||
cameraManager.closeDriver();
|
||||
if (!hasSurface) {
|
||||
surfaceHolder.removeCallback(callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Activity#onDestroy()}
|
||||
*/
|
||||
@Override
|
||||
public void onDestroy(){
|
||||
inactivityTimer.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* 支持缩放时,须在{@link Activity#onTouchEvent(MotionEvent)}调用此方法
|
||||
* @param event
|
||||
*/
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event){
|
||||
if(isSupportZoom && cameraManager.isOpen()){
|
||||
Camera camera = cameraManager.getOpenCamera().getCamera();
|
||||
if(camera ==null){
|
||||
return false;
|
||||
}
|
||||
if(event.getPointerCount() > 1) {
|
||||
switch (event.getAction() & MotionEvent.ACTION_MASK) {//多点触控
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
oldDistance = calcFingerSpacing(event);
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
float newDistance = calcFingerSpacing(event);
|
||||
|
||||
if (newDistance > oldDistance + DEVIATION) {//
|
||||
handleZoom(true, camera);
|
||||
} else if (newDistance < oldDistance - DEVIATION) {
|
||||
handleZoom(false, camera);
|
||||
}
|
||||
oldDistance = newDistance;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void initCamera(SurfaceHolder surfaceHolder) {
|
||||
if (surfaceHolder == null) {
|
||||
throw new IllegalStateException("No SurfaceHolder provided");
|
||||
}
|
||||
if (cameraManager.isOpen()) {
|
||||
Log.w(TAG, "initCamera() while already open -- late SurfaceView callback?");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
cameraManager.openDriver(surfaceHolder);
|
||||
// Creating the handler starts the preview, which can also throw a RuntimeException.
|
||||
if (captureHandler == null) {
|
||||
captureHandler = new CaptureHandler(activity,viewfinderView,onCaptureListener, decodeFormats, decodeHints, characterSet, cameraManager);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
Log.w(TAG, ioe);
|
||||
} catch (RuntimeException e) {
|
||||
// Barcode Scanner has seen crashes in the wild of this variety:
|
||||
// java.?lang.?RuntimeException: Fail to connect to camera service
|
||||
Log.w(TAG, "Unexpected error initializing camera", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理变焦缩放
|
||||
* @param isZoomIn
|
||||
* @param camera
|
||||
*/
|
||||
private void handleZoom(boolean isZoomIn, Camera camera) {
|
||||
Camera.Parameters params = camera.getParameters();
|
||||
if (params.isZoomSupported()) {
|
||||
int maxZoom = params.getMaxZoom();
|
||||
int zoom = params.getZoom();
|
||||
if (isZoomIn && zoom < maxZoom) {
|
||||
zoom++;
|
||||
} else if (zoom > 0) {
|
||||
zoom--;
|
||||
}
|
||||
params.setZoom(zoom);
|
||||
camera.setParameters(params);
|
||||
} else {
|
||||
Log.i(TAG, "zoom not supported");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 聚焦
|
||||
* @param event
|
||||
* @param camera
|
||||
*/
|
||||
private void focusOnTouch(MotionEvent event,Camera camera) {
|
||||
|
||||
Camera.Parameters params = camera.getParameters();
|
||||
Camera.Size previewSize = params.getPreviewSize();
|
||||
|
||||
Rect focusRect = calcTapArea(event.getRawX(), event.getRawY(), 1f,previewSize);
|
||||
Rect meteringRect = calcTapArea(event.getRawX(), event.getRawY(), 1.5f,previewSize);
|
||||
Camera.Parameters parameters = camera.getParameters();
|
||||
if (parameters.getMaxNumFocusAreas() > 0) {
|
||||
List<Camera.Area> focusAreas = new ArrayList<>();
|
||||
focusAreas.add(new Camera.Area(focusRect, 600));
|
||||
parameters.setFocusAreas(focusAreas);
|
||||
}
|
||||
|
||||
if (parameters.getMaxNumMeteringAreas() > 0) {
|
||||
List<Camera.Area> meteringAreas = new ArrayList<>();
|
||||
meteringAreas.add(new Camera.Area(meteringRect, 600));
|
||||
parameters.setMeteringAreas(meteringAreas);
|
||||
}
|
||||
final String currentFocusMode = params.getFocusMode();
|
||||
params.setFocusMode(Camera.Parameters.FOCUS_MODE_MACRO);
|
||||
camera.setParameters(params);
|
||||
|
||||
camera.autoFocus(new Camera.AutoFocusCallback() {
|
||||
@Override
|
||||
public void onAutoFocus(boolean success, Camera camera) {
|
||||
Camera.Parameters params = camera.getParameters();
|
||||
params.setFocusMode(currentFocusMode);
|
||||
camera.setParameters(params);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 计算两指间距离
|
||||
* @param event
|
||||
* @return
|
||||
*/
|
||||
private float calcFingerSpacing(MotionEvent event) {
|
||||
float x = event.getX(0) - event.getX(1);
|
||||
float y = event.getY(0) - event.getY(1);
|
||||
return (float) Math.sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算对焦区域
|
||||
* @param x
|
||||
* @param y
|
||||
* @param coefficient
|
||||
* @param previewSize
|
||||
* @return
|
||||
*/
|
||||
private Rect calcTapArea(float x, float y, float coefficient, Camera.Size previewSize) {
|
||||
float focusAreaSize = 200;
|
||||
int areaSize = Float.valueOf(focusAreaSize * coefficient).intValue();
|
||||
int centerX = (int) ((x / previewSize.width) * 2000 - 1000);
|
||||
int centerY = (int) ((y / previewSize.height) * 2000 - 1000);
|
||||
int left = clamp(centerX - (areaSize / 2), -1000, 1000);
|
||||
int top = clamp(centerY - (areaSize / 2), -1000, 1000);
|
||||
RectF rectF = new RectF(left, top, left + areaSize, top + areaSize);
|
||||
return new Rect(Math.round(rectF.left), Math.round(rectF.top),
|
||||
Math.round(rectF.right), Math.round(rectF.bottom));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param x
|
||||
* @param min
|
||||
* @param max
|
||||
* @return
|
||||
*/
|
||||
private int clamp(int x, int min, int max) {
|
||||
if (x > max) {
|
||||
return max;
|
||||
}
|
||||
if (x < min) {
|
||||
return min;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 重新启动扫码和解码器
|
||||
*/
|
||||
public void restartPreviewAndDecode(){
|
||||
if(captureHandler!=null){
|
||||
captureHandler.restartPreviewAndDecode();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收扫码结果,想支持连扫时,可将{@link #continuousScan(boolean)}设置为{@code true}
|
||||
* 如果{@link #isContinuousScan}支持连扫,则默认重启扫码和解码器;当连扫逻辑太复杂时,
|
||||
* 请将{@link #autoRestartPreviewAndDecode(boolean)}设置为{@code false},并手动调用{@link #restartPreviewAndDecode()}
|
||||
* @param result 扫码结果
|
||||
*/
|
||||
public void onResult(Result result){
|
||||
String text = result.getText();
|
||||
if(isContinuousScan){
|
||||
if(isAutoRestartPreviewAndDecode){
|
||||
if(onCaptureCallback!=null){
|
||||
onCaptureCallback.onResultCallback(text);
|
||||
}
|
||||
restartPreviewAndDecode();
|
||||
}
|
||||
}else{
|
||||
//如果设置了回调,并且onCallback返回为true,则表示拦截
|
||||
if(onCaptureCallback!=null && onCaptureCallback.onResultCallback(text)){
|
||||
return;
|
||||
}
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(Intents.Scan.RESULT,text);
|
||||
activity.setResult(Activity.RESULT_OK,intent);
|
||||
activity.finish();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否连续扫码,如果想支持连续扫码,则将此方法返回{@code true}并重写{@link #onResult(Result)}
|
||||
*/
|
||||
public CaptureHelper continuousScan(boolean isContinuousScan){
|
||||
this.isContinuousScan = isContinuousScan;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置是否自动重启扫码和解码器,当支持连扫时才起作用。
|
||||
* @return 默认返回 true
|
||||
*/
|
||||
public CaptureHelper autoRestartPreviewAndDecode(boolean isAutoRestartPreviewAndDecode){
|
||||
this.isAutoRestartPreviewAndDecode = isAutoRestartPreviewAndDecode;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置是否播放音效
|
||||
* @return
|
||||
*/
|
||||
public CaptureHelper playBeep(boolean playBeep){
|
||||
this.isPlayBeep = playBeep;
|
||||
if(beepManager!=null){
|
||||
beepManager.setPlayBeep(playBeep);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否震动
|
||||
* @return
|
||||
*/
|
||||
public CaptureHelper vibrate(boolean vibrate){
|
||||
this.isVibrate = vibrate;
|
||||
if(beepManager!=null){
|
||||
beepManager.setVibrate(vibrate);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置是否支持缩放
|
||||
* @param supportZoom
|
||||
* @return
|
||||
*/
|
||||
public CaptureHelper supportZoom(boolean supportZoom) {
|
||||
isSupportZoom = supportZoom;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param decodeFormats
|
||||
* @return
|
||||
*/
|
||||
public CaptureHelper decodeFormats(Collection<BarcodeFormat> decodeFormats) {
|
||||
this.decodeFormats = decodeFormats;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param decodeHints
|
||||
* @return
|
||||
*/
|
||||
public CaptureHelper decodeHints(Map<DecodeHintType,?> decodeHints) {
|
||||
this.decodeHints = decodeHints;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param characterSet
|
||||
* @return
|
||||
*/
|
||||
public CaptureHelper characterSet(String characterSet) {
|
||||
this.characterSet = characterSet;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置扫码回调
|
||||
* @param callback
|
||||
* @return
|
||||
*/
|
||||
public CaptureHelper setOnCaptureCallback(OnCaptureCallback callback) {
|
||||
this.onCaptureCallback = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CameraManager getCameraManager() {
|
||||
return cameraManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeepManager getBeepManager() {
|
||||
return beepManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AmbientLightManager getAmbientLightManager() {
|
||||
return ambientLightManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InactivityTimer getInactivityTimer() {
|
||||
return inactivityTimer;
|
||||
}
|
||||
}
|
||||
45
lib/src/main/java/com/king/zxing/CaptureLifecycle.java
Normal file
45
lib/src/main/java/com/king/zxing/CaptureLifecycle.java
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Jenly Yu
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.king.zxing;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public interface CaptureLifecycle {
|
||||
|
||||
/**
|
||||
* {@link android.app.Activity#onCreate(Bundle)}
|
||||
*/
|
||||
void onCreate();
|
||||
/**
|
||||
* {@link Activity#onResume()}
|
||||
*/
|
||||
void onResume();
|
||||
|
||||
/**
|
||||
* {@link Activity#onPause()}
|
||||
*/
|
||||
void onPause();
|
||||
|
||||
/**
|
||||
* {@link Activity#onDestroy()}
|
||||
*/
|
||||
void onDestroy();
|
||||
|
||||
}
|
||||
48
lib/src/main/java/com/king/zxing/CaptureManager.java
Normal file
48
lib/src/main/java/com/king/zxing/CaptureManager.java
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Jenly Yu
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.king.zxing;
|
||||
|
||||
import com.king.zxing.camera.CameraManager;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public interface CaptureManager {
|
||||
|
||||
/**
|
||||
* Get {@link CameraManager}
|
||||
* @return {@link CameraManager}
|
||||
*/
|
||||
CameraManager getCameraManager();
|
||||
|
||||
/**
|
||||
* Get {@link BeepManager}
|
||||
* @return {@link BeepManager}
|
||||
*/
|
||||
BeepManager getBeepManager();
|
||||
|
||||
/**
|
||||
* Get {@link AmbientLightManager}
|
||||
* @return {@link AmbientLightManager}
|
||||
*/
|
||||
AmbientLightManager getAmbientLightManager();
|
||||
|
||||
/**
|
||||
* Get {@link InactivityTimer}
|
||||
* @return {@link InactivityTimer}
|
||||
*/
|
||||
InactivityTimer getInactivityTimer();
|
||||
}
|
||||
29
lib/src/main/java/com/king/zxing/CaptureTouchEvent.java
Normal file
29
lib/src/main/java/com/king/zxing/CaptureTouchEvent.java
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Jenly Yu
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.king.zxing;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public interface CaptureTouchEvent {
|
||||
|
||||
/**
|
||||
* {@link android.app.Activity#onTouchEvent(MotionEvent)}
|
||||
*/
|
||||
boolean onTouchEvent(MotionEvent event);
|
||||
}
|
||||
@@ -23,10 +23,10 @@ import com.google.zxing.DecodeHintType;
|
||||
import com.google.zxing.MultiFormatReader;
|
||||
import com.google.zxing.NotFoundException;
|
||||
import com.google.zxing.PlanarYUVLuminanceSource;
|
||||
import com.google.zxing.ReaderException;
|
||||
import com.google.zxing.Result;
|
||||
import com.google.zxing.common.GlobalHistogramBinarizer;
|
||||
import com.google.zxing.common.HybridBinarizer;
|
||||
import com.king.zxing.camera.CameraManager;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.os.Bundle;
|
||||
@@ -44,14 +44,18 @@ final class DecodeHandler extends Handler {
|
||||
|
||||
private static final String TAG = DecodeHandler.class.getSimpleName();
|
||||
|
||||
private final CaptureActivity activity;
|
||||
private final Context context;
|
||||
private final CameraManager cameraManager;
|
||||
private final Handler handler;
|
||||
private final MultiFormatReader multiFormatReader;
|
||||
private boolean running = true;
|
||||
|
||||
DecodeHandler(CaptureActivity activity, Map<DecodeHintType,Object> hints) {
|
||||
DecodeHandler(Context context, CameraManager cameraManager,Handler handler, Map<DecodeHintType,Object> hints) {
|
||||
multiFormatReader = new MultiFormatReader();
|
||||
multiFormatReader.setHints(hints);
|
||||
this.activity = activity;
|
||||
this.context = context;
|
||||
this.cameraManager = cameraManager;
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -70,7 +74,7 @@ final class DecodeHandler extends Handler {
|
||||
}
|
||||
|
||||
private boolean isScreenPortrait(){
|
||||
WindowManager manager = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
|
||||
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||
Display display = manager.getDefaultDisplay();
|
||||
Point screenResolution = new Point();
|
||||
display.getSize(screenResolution);
|
||||
@@ -98,9 +102,9 @@ final class DecodeHandler extends Handler {
|
||||
int tmp = width;
|
||||
width = height;
|
||||
height = tmp;
|
||||
source = activity.getCameraManager().buildLuminanceSource(rotatedData, width, height);
|
||||
source = cameraManager.buildLuminanceSource(rotatedData, width, height);
|
||||
}else{
|
||||
source = activity.getCameraManager().buildLuminanceSource(data, width, height);
|
||||
source = cameraManager.buildLuminanceSource(data, width, height);
|
||||
}
|
||||
if (source != null) {
|
||||
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||
@@ -118,7 +122,6 @@ final class DecodeHandler extends Handler {
|
||||
}
|
||||
}
|
||||
|
||||
Handler handler = activity.getHandler();
|
||||
if (rawResult != null) {
|
||||
// Don't log the barcode contents for security.
|
||||
long end = System.currentTimeMillis();
|
||||
|
||||
@@ -20,7 +20,9 @@ package com.king.zxing;
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.DecodeHintType;
|
||||
import com.google.zxing.ResultPointCallback;
|
||||
import com.king.zxing.camera.CameraManager;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
@@ -43,18 +45,23 @@ final class DecodeThread extends Thread {
|
||||
public static final String BARCODE_BITMAP = "barcode_bitmap";
|
||||
public static final String BARCODE_SCALED_FACTOR = "barcode_scaled_factor";
|
||||
|
||||
private final CaptureActivity activity;
|
||||
private final Context context;
|
||||
private final CameraManager cameraManager;
|
||||
private final Map<DecodeHintType,Object> hints;
|
||||
private Handler handler;
|
||||
private CaptureHandler captureHandler;
|
||||
private final CountDownLatch handlerInitLatch;
|
||||
|
||||
DecodeThread(CaptureActivity activity,
|
||||
DecodeThread(Context context,CameraManager cameraManager,
|
||||
CaptureHandler captureHandler,
|
||||
Collection<BarcodeFormat> decodeFormats,
|
||||
Map<DecodeHintType,?> baseHints,
|
||||
String characterSet,
|
||||
ResultPointCallback resultPointCallback) {
|
||||
|
||||
this.activity = activity;
|
||||
this.context = context;
|
||||
this.cameraManager = cameraManager;
|
||||
this.captureHandler = captureHandler;
|
||||
handlerInitLatch = new CountDownLatch(1);
|
||||
|
||||
hints = new EnumMap<>(DecodeHintType.class);
|
||||
@@ -64,7 +71,7 @@ final class DecodeThread extends Thread {
|
||||
|
||||
// The prefs can't change while the thread is running, so pick them up once here.
|
||||
if (decodeFormats == null || decodeFormats.isEmpty()) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
decodeFormats = EnumSet.noneOf(BarcodeFormat.class);
|
||||
if (prefs.getBoolean(Preferences.KEY_DECODE_1D_PRODUCT, true)) {
|
||||
decodeFormats.addAll(DecodeFormatManager.PRODUCT_FORMATS);
|
||||
@@ -106,7 +113,7 @@ final class DecodeThread extends Thread {
|
||||
@Override
|
||||
public void run() {
|
||||
Looper.prepare();
|
||||
handler = new DecodeHandler(activity, hints);
|
||||
handler = new DecodeHandler(context,cameraManager,captureHandler, hints);
|
||||
handlerInitLatch.countDown();
|
||||
Looper.loop();
|
||||
}
|
||||
|
||||
16
lib/src/main/java/com/king/zxing/OnCaptureCallback.java
Normal file
16
lib/src/main/java/com/king/zxing/OnCaptureCallback.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package com.king.zxing;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public interface OnCaptureCallback {
|
||||
|
||||
/**
|
||||
* 接收扫码结果回调
|
||||
* @param result 扫码结果
|
||||
* @return 返回true表示拦截,将不自动执行后续逻辑,为false表示不拦截
|
||||
*/
|
||||
boolean onResultCallback(String result);
|
||||
}
|
||||
22
lib/src/main/java/com/king/zxing/OnCaptureListener.java
Normal file
22
lib/src/main/java/com/king/zxing/OnCaptureListener.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package com.king.zxing;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
import com.google.zxing.Result;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public interface OnCaptureListener {
|
||||
|
||||
|
||||
/**
|
||||
* 接收解码后的扫码结果
|
||||
* @param result
|
||||
* @param barcode
|
||||
* @param scaleFactor
|
||||
*/
|
||||
void onHandleDecode(Result result, Bitmap barcode, float scaleFactor);
|
||||
|
||||
|
||||
}
|
||||
@@ -66,7 +66,7 @@ public final class CameraManager {
|
||||
private final PreviewCallback previewCallback;
|
||||
|
||||
public CameraManager(Context context) {
|
||||
this.context = context;
|
||||
this.context = context.getApplicationContext();
|
||||
this.configManager = new CameraConfigurationManager(context);
|
||||
previewCallback = new PreviewCallback(configManager);
|
||||
}
|
||||
|
||||
@@ -1,25 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2008 ZXing authors
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<SurfaceView
|
||||
android:id="@+id/preview_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
<com.king.zxing.ViewfinderView
|
||||
android:id="@+id/viewfinder_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
</merge>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2008 ZXing authors
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<SurfaceView
|
||||
android:id="@+id/surfaceView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
<com.king.zxing.ViewfinderView
|
||||
android:id="@+id/viewfinderView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
</FrameLayout>
|
||||
@@ -4,7 +4,7 @@
|
||||
<color name="viewfinder_mask">#60000000</color>
|
||||
<color name="viewfinder_frame">#7F1FB3E2</color>
|
||||
<color name="viewfinder_corner">#FF1FB3E2</color>
|
||||
<color name="viewfinder_laser">#FF1FB3E2</color> <!-- Android standard ICS color -->
|
||||
<color name="viewfinder_laser">#FF1FB3E2</color>
|
||||
<color name="viewfinder_result_point_color">#C0FFBD21</color>
|
||||
<color name="viewfinder_text_color">#FFC0C0C0</color>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//App
|
||||
def app_version = [:]
|
||||
app_version.versionCode = 8
|
||||
app_version.versionName = "1.0.7"
|
||||
app_version.versionCode = 9
|
||||
app_version.versionName = "1.1.0"
|
||||
ext.app_version = app_version
|
||||
|
||||
//build version
|
||||
|
||||
Reference in New Issue
Block a user