37 |
38 | ## 手电筒开关会在光线若的情况下自动打开
39 |
40 |
41 | ## 读取相册 使用相机权限也已经封装
42 |
43 | ## 参数
44 | ### req:回调结果code
45 | ### needAlbum:是否需要相册选择
46 |
47 | ### 请求示例
48 | ```
49 | ScanActivity.start(ManiActivity.this,123);
50 | ```
51 | ### 回调处理
52 | ```
53 | @Override
54 | protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
55 | super.onActivityResult(requestCode, resultCode, data);
56 | switch (requestCode){
57 | case 123:
58 | if(resultCode == RESULT_OK){
59 | String type = data.getStringExtra(CodeUtils.RESULT_TYPE);
60 | String result = data.getStringExtra(CodeUtils.RESULT_STRING);
61 | if(type.equals(CodeUtils.RESULT_SUCCESS)){
62 | Toast.makeText(this,result,Toast.LENGTH_SHORT).show();
63 | }else {
64 | Toast.makeText(this,"扫描失败",Toast.LENGTH_SHORT).show();
65 | }
66 | }
67 | break;
68 | default:break;
69 | }
70 |
71 | }
72 | ```
73 |
74 | ## License
75 | Copyright 2018 Winton
76 |
77 | Licensed under the Apache License, Version 2.0 (the "License");
78 | you may not use this file except in compliance with the License.
79 | You may obtain a copy of the License at
80 |
81 | http://www.apache.org/licenses/LICENSE-2.0
82 |
83 | Unless required by applicable law or agreed to in writing, software
84 | distributed under the License is distributed on an "AS IS" BASIS,
85 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
86 | See the License for the specific language governing permissions and
87 | limitations under the License.
88 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 28
5 | defaultConfig {
6 | applicationId "com.winton.easyzxing"
7 | minSdkVersion 15
8 | targetSdkVersion 28
9 | versionCode 1
10 | versionName "1.0"
11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | implementation fileTree(include: ['*.jar'], dir: 'libs')
23 | implementation 'com.android.support:appcompat-v7:28.0.0-rc02'
24 | implementation 'com.android.support.constraint:constraint-layout:1.1.3'
25 | testImplementation 'junit:junit:4.12'
26 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
27 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
28 |
29 | implementation 'com.github.wintonBy:EasyZxing:1.0'
30 | }
31 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/winton/easyzxing/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.winton.easyzxing
2 |
3 | import android.support.test.InstrumentationRegistry
4 | import android.support.test.runner.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getTargetContext()
22 | assertEquals("com.winton.easyzxing", appContext.packageName)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/winton/easyzxing/ManiActivity.java:
--------------------------------------------------------------------------------
1 | package com.winton.easyzxing;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.v7.app.AppCompatActivity;
7 | import android.view.View;
8 | import android.widget.TextView;
9 | import android.widget.Toast;
10 |
11 | import com.zxing.activity.CodeUtils;
12 | import com.zxing.activity.ScanActivity;
13 |
14 | import javax.xml.transform.Result;
15 |
16 | /**
17 | * @author: winton
18 | * @time: 2018/9/6 下午6:24
19 | * @desc: 描述
20 | */
21 | public class ManiActivity extends AppCompatActivity {
22 |
23 | TextView textView ;
24 |
25 | @Override
26 | protected void onCreate(@Nullable Bundle savedInstanceState) {
27 | super.onCreate(savedInstanceState);
28 | textView = new TextView(this);
29 | textView.setText("点击这里");
30 | setContentView(textView);
31 | textView.setOnClickListener(new View.OnClickListener() {
32 | @Override
33 | public void onClick(View v) {
34 | ScanActivity.start(ManiActivity.this,123);
35 | }
36 | });
37 | }
38 |
39 |
40 | @Override
41 | protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
42 | super.onActivityResult(requestCode, resultCode, data);
43 | switch (requestCode){
44 | case 123:
45 | if(resultCode == RESULT_OK){
46 | int type = data.getIntExtra(CodeUtils.RESULT_TYPE,-1);
47 | String result = data.getStringExtra(CodeUtils.RESULT_STRING);
48 | if(type == CodeUtils.RESULT_SUCCESS){
49 | Toast.makeText(this,result,Toast.LENGTH_SHORT).show();
50 | }else {
51 | Toast.makeText(this,"扫描失败",Toast.LENGTH_SHORT).show();
52 | }
53 | }
54 | break;
55 | default:break;
56 | }
57 |
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wintonBy/EasyZxing/91dc97f7c2bcb086bba93f4c6b1d2051a8a6b02c/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wintonBy/EasyZxing/91dc97f7c2bcb086bba93f4c6b1d2051a8a6b02c/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wintonBy/EasyZxing/91dc97f7c2bcb086bba93f4c6b1d2051a8a6b02c/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wintonBy/EasyZxing/91dc97f7c2bcb086bba93f4c6b1d2051a8a6b02c/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wintonBy/EasyZxing/91dc97f7c2bcb086bba93f4c6b1d2051a8a6b02c/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wintonBy/EasyZxing/91dc97f7c2bcb086bba93f4c6b1d2051a8a6b02c/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wintonBy/EasyZxing/91dc97f7c2bcb086bba93f4c6b1d2051a8a6b02c/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wintonBy/EasyZxing/91dc97f7c2bcb086bba93f4c6b1d2051a8a6b02c/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wintonBy/EasyZxing/91dc97f7c2bcb086bba93f4c6b1d2051a8a6b02c/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wintonBy/EasyZxing/91dc97f7c2bcb086bba93f4c6b1d2051a8a6b02c/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | EasyZxing
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/com/winton/easyzxing/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.winton.easyzxing
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | google()
6 | jcenter()
7 | }
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.1.4'
10 |
11 | // NOTE: Do not place your application dependencies here; they belong
12 | // in the individual module build.gradle files
13 | }
14 | }
15 |
16 | allprojects {
17 | repositories {
18 | google()
19 | jcenter()
20 | maven { url 'https://jitpack.io' }
21 | }
22 | }
23 |
24 | task clean(type: Delete) {
25 | delete rootProject.buildDir
26 | }
27 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wintonBy/EasyZxing/91dc97f7c2bcb086bba93f4c6b1d2051a8a6b02c/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Sep 06 16:55:30 CST 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/screen/screen.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wintonBy/EasyZxing/91dc97f7c2bcb086bba93f4c6b1d2051a8a6b02c/screen/screen.jpg
--------------------------------------------------------------------------------
/screen/screen1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wintonBy/EasyZxing/91dc97f7c2bcb086bba93f4c6b1d2051a8a6b02c/screen/screen1.jpg
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app',':zxing'
2 |
--------------------------------------------------------------------------------
/zxing/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/zxing/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 28
5 | defaultConfig {
6 | minSdkVersion 15
7 | targetSdkVersion 28
8 | versionCode 1
9 | versionName "1.0"
10 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
11 | }
12 |
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 |
20 | }
21 |
22 | dependencies {
23 | implementation fileTree(dir: 'libs', include: ['*.jar'])
24 |
25 | implementation 'com.android.support:appcompat-v7:28.0.0-rc02'
26 |
27 | // 二维码扫描
28 | implementation files('libs/zxing_core_3.0.1.jar')
29 | }
30 |
--------------------------------------------------------------------------------
/zxing/libs/zxing_core_3.0.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wintonBy/EasyZxing/91dc97f7c2bcb086bba93f4c6b1d2051a8a6b02c/zxing/libs/zxing_core_3.0.1.jar
--------------------------------------------------------------------------------
/zxing/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/zxing/src/androidTest/java/com/zxing/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.zxing;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.zxing.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/zxing/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
13 |
14 |
21 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/DisplayUtil.java:
--------------------------------------------------------------------------------
1 | package com.zxing;
2 |
3 | import android.content.Context;
4 |
5 | /**
6 | * Created by aaron on 16/8/3.
7 | */
8 | public class DisplayUtil
9 | {
10 |
11 | public static int screenWidthPx; //屏幕宽 px
12 | public static int screenhightPx; //屏幕高 px
13 | public static float density;//屏幕密度
14 | public static int densityDPI;//屏幕密度
15 | public static float screenWidthDip;// dp单位
16 | public static float screenHightDip;// dp单位
17 |
18 |
19 |
20 | /**
21 | * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
22 | */
23 | public static int dip2px(Context context, float dpValue) {
24 | final float scale = context.getResources().getDisplayMetrics().density;
25 | return (int) (dpValue * scale + 0.5f);
26 | }
27 |
28 | /**
29 | * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
30 | */
31 | public static int px2dip(Context context, float pxValue) {
32 | final float scale = context.getResources().getDisplayMetrics().density;
33 | return (int) (pxValue / scale + 0.5f);
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/UriUtils.java:
--------------------------------------------------------------------------------
1 | package com.zxing;
2 |
3 | import android.content.ContentUris;
4 | import android.content.Context;
5 | import android.database.Cursor;
6 | import android.net.Uri;
7 | import android.os.Build;
8 | import android.os.Environment;
9 | import android.provider.DocumentsContract;
10 | import android.provider.MediaStore;
11 |
12 | /**
13 | * @author: winton
14 | * @time: 2018/8/10 15:19
15 | * @package: com.android.wasu.enjoytv.utils
16 | * @project: wasuenjoytv
17 | * @mail:
18 | * @describe: 一句话描述
19 | */
20 | public class UriUtils {
21 |
22 | public static String getPath(final Context context, final Uri uri) {
23 |
24 | final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
25 |
26 | // DocumentProvider
27 | if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
28 | // ExternalStorageProvider
29 | if (isExternalStorageDocument(uri)) {
30 | final String docId = DocumentsContract.getDocumentId(uri);
31 | final String[] split = docId.split(":");
32 | final String type = split[0];
33 |
34 | if ("primary".equalsIgnoreCase(type)) {
35 | return Environment.getExternalStorageDirectory() + "/"
36 | + split[1];
37 | }
38 |
39 | // TODO handle non-primary volumes
40 | }
41 | // DownloadsProvider
42 | else if (isDownloadsDocument(uri)) {
43 |
44 | final String id = DocumentsContract.getDocumentId(uri);
45 | final Uri contentUri = ContentUris.withAppendedId(
46 | Uri.parse("content://downloads/public_downloads"),
47 | Long.valueOf(id));
48 |
49 | return getDataColumn(context, contentUri, null, null);
50 | }
51 | // MediaProvider
52 | else if (isMediaDocument(uri)) {
53 | final String docId = DocumentsContract.getDocumentId(uri);
54 | final String[] split = docId.split(":");
55 | final String type = split[0];
56 |
57 | Uri contentUri = null;
58 | if ("image".equals(type)) {
59 | contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
60 | } else if ("video".equals(type)) {
61 | contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
62 | } else if ("audio".equals(type)) {
63 | contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
64 | }
65 |
66 | final String selection = "_id=?";
67 | final String[] selectionArgs = new String[] { split[1] };
68 |
69 | return getDataColumn(context, contentUri, selection,
70 | selectionArgs);
71 | }
72 | }
73 | // MediaStore (and general)
74 | else if ("content".equalsIgnoreCase(uri.getScheme())) {
75 | return getDataColumn(context, uri, null, null);
76 | }
77 | // File
78 | else if ("file".equalsIgnoreCase(uri.getScheme())) {
79 | return uri.getPath();
80 | }
81 |
82 | return null;
83 | }
84 |
85 | /**
86 | * Get the value of the data column for this Uri. This is useful for
87 | * MediaStore Uris, and other file-based ContentProviders.
88 | *
89 | * @param context
90 | * The context.
91 | * @param uri
92 | * The Uri to query.
93 | * @param selection
94 | * (Optional) Filter used in the query.
95 | * @param selectionArgs
96 | * (Optional) Selection arguments used in the query.
97 | * @return The value of the _data column, which is typically a file path.
98 | */
99 | public static String getDataColumn(Context context, Uri uri,
100 | String selection, String[] selectionArgs) {
101 |
102 | Cursor cursor = null;
103 | final String column = "_data";
104 | final String[] projection = { column };
105 |
106 | try {
107 | cursor = context.getContentResolver().query(uri, projection,
108 | selection, selectionArgs, null);
109 | if (cursor != null && cursor.moveToFirst()) {
110 | final int column_index = cursor.getColumnIndexOrThrow(column);
111 | return cursor.getString(column_index);
112 | }
113 | } finally {
114 | if (cursor != null)
115 | cursor.close();
116 | }
117 | return null;
118 | }
119 |
120 | /**
121 | * @param uri
122 | * The Uri to check.
123 | * @return Whether the Uri authority is ExternalStorageProvider.
124 | */
125 | public static boolean isExternalStorageDocument(Uri uri) {
126 | return "com.android.externalstorage.documents".equals(uri
127 | .getAuthority());
128 | }
129 |
130 | /**
131 | * @param uri
132 | * The Uri to check.
133 | * @return Whether the Uri authority is DownloadsProvider.
134 | */
135 | public static boolean isDownloadsDocument(Uri uri) {
136 | return "com.android.providers.downloads.documents".equals(uri
137 | .getAuthority());
138 | }
139 |
140 | /**
141 | * @param uri
142 | * The Uri to check.
143 | * @return Whether the Uri authority is MediaProvider.
144 | */
145 | public static boolean isMediaDocument(Uri uri) {
146 | return "com.android.providers.media.documents".equals(uri
147 | .getAuthority());
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/activity/CaptureActivity.java:
--------------------------------------------------------------------------------
1 | package com.zxing.activity;
2 |
3 | import android.content.Intent;
4 | import android.graphics.Bitmap;
5 | import android.os.Bundle;
6 | import android.support.v7.app.AppCompatActivity;
7 | import android.util.Log;
8 |
9 | import com.zxing.R;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 |
15 | /**
16 | * Initial the camera
17 | *
18 | * 默认的二维码扫描Activity
19 | */
20 | public class CaptureActivity extends AppCompatActivity {
21 |
22 |
23 | @Override
24 | protected void onCreate(Bundle savedInstanceState) {
25 |
26 | super.onCreate(savedInstanceState);
27 | setContentView(R.layout.camera);
28 | CaptureFragment captureFragment = new CaptureFragment();
29 | captureFragment.setAnalyzeCallback(analyzeCallback);
30 | getSupportFragmentManager().beginTransaction().replace(R.id.fl_zxing_container, captureFragment).commit();
31 | captureFragment.setCameraInitCallBack(new CaptureFragment.CameraInitCallBack() {
32 | @Override
33 | public void callBack(Exception e) {
34 | if (e == null) {
35 |
36 | } else {
37 | Log.e("TAG", "callBack: ", e);
38 | }
39 | }
40 | });
41 |
42 | }
43 |
44 | /**
45 | * 二维码解析回调函数
46 | */
47 | CodeUtils.AnalyzeCallback analyzeCallback = new CodeUtils.AnalyzeCallback() {
48 | @Override
49 | public void onAnalyzeSuccess(Bitmap mBitmap, String result) {
50 | Intent resultIntent = new Intent();
51 | Bundle bundle = new Bundle();
52 | bundle.putInt(CodeUtils.RESULT_TYPE, CodeUtils.RESULT_SUCCESS);
53 | bundle.putString(CodeUtils.RESULT_STRING, result);
54 | resultIntent.putExtras(bundle);
55 | CaptureActivity.this.setResult(RESULT_OK, resultIntent);
56 | CaptureActivity.this.finish();
57 | }
58 |
59 | @Override
60 | public void onAnalyzeFailed() {
61 | Intent resultIntent = new Intent();
62 | Bundle bundle = new Bundle();
63 | bundle.putInt(CodeUtils.RESULT_TYPE, CodeUtils.RESULT_FAILED);
64 | bundle.putString(CodeUtils.RESULT_STRING, "");
65 | resultIntent.putExtras(bundle);
66 | CaptureActivity.this.setResult(RESULT_OK, resultIntent);
67 | CaptureActivity.this.finish();
68 | }
69 | };
70 | }
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/activity/CaptureFragment.java:
--------------------------------------------------------------------------------
1 | package com.zxing.activity;
2 |
3 | import android.content.res.AssetFileDescriptor;
4 | import android.graphics.Bitmap;
5 | import android.hardware.Camera;
6 | import android.media.AudioManager;
7 | import android.media.MediaPlayer;
8 | import android.os.Bundle;
9 | import android.os.Handler;
10 | import android.os.Vibrator;
11 | import android.support.annotation.Nullable;
12 | import android.support.v4.app.Fragment;
13 | import android.text.TextUtils;
14 | import android.view.LayoutInflater;
15 | import android.view.SurfaceHolder;
16 | import android.view.SurfaceView;
17 | import android.view.View;
18 | import android.view.ViewGroup;
19 |
20 | import com.google.zxing.BarcodeFormat;
21 | import com.google.zxing.Result;
22 | import com.zxing.R;
23 | import com.zxing.camera.CameraManager;
24 | import com.zxing.decoding.CaptureActivityHandler;
25 | import com.zxing.decoding.InactivityTimer;
26 | import com.zxing.view.ViewfinderView;
27 |
28 | import java.io.IOException;
29 | import java.util.Vector;
30 |
31 | /**
32 | * 自定义实现的扫描Fragment
33 | */
34 | public class CaptureFragment extends Fragment implements SurfaceHolder.Callback {
35 |
36 | private CaptureActivityHandler handler;
37 | private ViewfinderView viewfinderView;
38 | private boolean hasSurface;
39 | private Vector decodeFormats;
40 | private String characterSet;
41 | private InactivityTimer inactivityTimer;
42 | private MediaPlayer mediaPlayer;
43 | private boolean playBeep;
44 | private static final float BEEP_VOLUME = 0.10f;
45 | private boolean vibrate;
46 | private SurfaceView surfaceView;
47 | private SurfaceHolder surfaceHolder;
48 | private CodeUtils.AnalyzeCallback analyzeCallback;
49 | private Camera camera;
50 |
51 | @Override
52 | public void onCreate(@Nullable Bundle savedInstanceState) {
53 | super.onCreate(savedInstanceState);
54 | CameraManager.init(getActivity().getApplication());
55 |
56 | hasSurface = false;
57 | inactivityTimer = new InactivityTimer(this.getActivity());
58 | }
59 |
60 | @Nullable
61 | @Override
62 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
63 |
64 | Bundle bundle = getArguments();
65 | View view = null;
66 | if (bundle != null) {
67 | int layoutId = bundle.getInt(CodeUtils.LAYOUT_ID);
68 | if (layoutId != -1) {
69 | view = inflater.inflate(layoutId, null);
70 | }
71 | }
72 |
73 | if (view == null) {
74 | view = inflater.inflate(R.layout.fragment_capture, null);
75 | }
76 |
77 | viewfinderView = (ViewfinderView) view.findViewById(R.id.viewfinder_view);
78 | surfaceView = (SurfaceView) view.findViewById(R.id.preview_view);
79 | surfaceHolder = surfaceView.getHolder();
80 |
81 | return view;
82 | }
83 |
84 | @Override
85 | public void onResume() {
86 | super.onResume();
87 | if (hasSurface) {
88 | initCamera(surfaceHolder);
89 | } else {
90 | surfaceHolder.addCallback(this);
91 | surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
92 | }
93 | decodeFormats = null;
94 | characterSet = null;
95 |
96 | playBeep = true;
97 | AudioManager audioService = (AudioManager) getActivity().getSystemService(getActivity().AUDIO_SERVICE);
98 | if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
99 | playBeep = false;
100 | }
101 | initBeepSound();
102 | vibrate = true;
103 | }
104 |
105 | @Override
106 | public void onPause() {
107 | super.onPause();
108 | if (handler != null) {
109 | handler.quitSynchronously();
110 | handler = null;
111 | }
112 | CameraManager.get().closeDriver();
113 | }
114 |
115 | @Override
116 | public void onDestroy() {
117 | super.onDestroy();
118 | inactivityTimer.shutdown();
119 | }
120 |
121 |
122 | /**
123 | * Handler scan result
124 | *
125 | * @param result
126 | * @param barcode
127 | */
128 | public void handleDecode(Result result, Bitmap barcode) {
129 | inactivityTimer.onActivity();
130 | playBeepSoundAndVibrate();
131 |
132 | if (result == null || TextUtils.isEmpty(result.getText())) {
133 | if (analyzeCallback != null) {
134 | analyzeCallback.onAnalyzeFailed();
135 | }
136 | } else {
137 | if (analyzeCallback != null) {
138 | analyzeCallback.onAnalyzeSuccess(barcode, result.getText());
139 | }
140 | }
141 | }
142 |
143 | private void initCamera(SurfaceHolder surfaceHolder) {
144 | try {
145 | CameraManager.get().openDriver(surfaceHolder);
146 | camera = CameraManager.get().getCamera();
147 | } catch (Exception e) {
148 | if (callBack != null) {
149 | callBack.callBack(e);
150 | }
151 | return;
152 | }
153 | if (callBack != null) {
154 | callBack.callBack(null);
155 | }
156 | if (handler == null) {
157 | handler = new CaptureActivityHandler(this, decodeFormats, characterSet, viewfinderView);
158 | }
159 | }
160 |
161 | @Override
162 | public void surfaceChanged(SurfaceHolder holder, int format, int width,
163 | int height) {
164 |
165 | }
166 |
167 | @Override
168 | public void surfaceCreated(SurfaceHolder holder) {
169 | if (!hasSurface) {
170 | hasSurface = true;
171 | initCamera(holder);
172 | }
173 |
174 | }
175 |
176 | @Override
177 | public void surfaceDestroyed(SurfaceHolder holder) {
178 | hasSurface = false;
179 | if (camera != null) {
180 | if (camera != null && CameraManager.get().isPreviewing()) {
181 | if (!CameraManager.get().isUseOneShotPreviewCallback()) {
182 | camera.setPreviewCallback(null);
183 | }
184 | camera.stopPreview();
185 | CameraManager.get().getPreviewCallback().setHandler(null, 0);
186 | CameraManager.get().getAutoFocusCallback().setHandler(null, 0);
187 | CameraManager.get().setPreviewing(false);
188 | }
189 | }
190 | }
191 |
192 | public Handler getHandler() {
193 | return handler;
194 | }
195 |
196 | public void drawViewfinder() {
197 | viewfinderView.drawViewfinder();
198 |
199 | }
200 |
201 | private void initBeepSound() {
202 | if (playBeep && mediaPlayer == null) {
203 | // The volume on STREAM_SYSTEM is not adjustable, and users found it
204 | // too loud,
205 | // so we now play on the music stream.
206 | getActivity().setVolumeControlStream(AudioManager.STREAM_MUSIC);
207 | mediaPlayer = new MediaPlayer();
208 | mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
209 | mediaPlayer.setOnCompletionListener(beepListener);
210 |
211 | AssetFileDescriptor file = getResources().openRawResourceFd(
212 | R.raw.beep);
213 | try {
214 | mediaPlayer.setDataSource(file.getFileDescriptor(),
215 | file.getStartOffset(), file.getLength());
216 | file.close();
217 | mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME);
218 | mediaPlayer.prepare();
219 | } catch (IOException e) {
220 | mediaPlayer = null;
221 | }
222 | }
223 | }
224 |
225 | private static final long VIBRATE_DURATION = 200L;
226 |
227 | private void playBeepSoundAndVibrate() {
228 | if (playBeep && mediaPlayer != null) {
229 | mediaPlayer.start();
230 | }
231 | if (vibrate) {
232 | Vibrator vibrator = (Vibrator) getActivity().getSystemService(getActivity().VIBRATOR_SERVICE);
233 | vibrator.vibrate(VIBRATE_DURATION);
234 | }
235 | }
236 |
237 | /**
238 | * When the beep has finished playing, rewind to queue up another one.
239 | */
240 | private final MediaPlayer.OnCompletionListener beepListener = new MediaPlayer.OnCompletionListener() {
241 | public void onCompletion(MediaPlayer mediaPlayer) {
242 | mediaPlayer.seekTo(0);
243 | }
244 | };
245 |
246 | public CodeUtils.AnalyzeCallback getAnalyzeCallback() {
247 | return analyzeCallback;
248 | }
249 |
250 | public void setAnalyzeCallback(CodeUtils.AnalyzeCallback analyzeCallback) {
251 | this.analyzeCallback = analyzeCallback;
252 | }
253 |
254 | @Nullable
255 | CameraInitCallBack callBack;
256 |
257 | /**
258 | * Set callback for Camera check whether Camera init success or not.
259 | */
260 | public void setCameraInitCallBack(CameraInitCallBack callBack) {
261 | this.callBack = callBack;
262 | }
263 |
264 | interface CameraInitCallBack {
265 | /**
266 | * Callback for Camera init result.
267 | * @param e If is's null,means success.otherwise Camera init failed with the Exception.
268 | */
269 | void callBack(Exception e);
270 | }
271 |
272 |
273 | }
274 |
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/activity/CodeUtils.java:
--------------------------------------------------------------------------------
1 | package com.zxing.activity;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.BitmapFactory;
5 | import android.graphics.Canvas;
6 | import android.graphics.Matrix;
7 | import android.hardware.Camera;
8 | import android.os.Bundle;
9 | import android.text.TextUtils;
10 |
11 | import com.google.zxing.BarcodeFormat;
12 | import com.google.zxing.BinaryBitmap;
13 | import com.google.zxing.DecodeHintType;
14 | import com.google.zxing.EncodeHintType;
15 | import com.google.zxing.MultiFormatReader;
16 | import com.google.zxing.Result;
17 | import com.google.zxing.WriterException;
18 | import com.google.zxing.common.BitMatrix;
19 | import com.google.zxing.common.HybridBinarizer;
20 | import com.google.zxing.qrcode.QRCodeWriter;
21 | import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
22 | import com.zxing.camera.BitmapLuminanceSource;
23 | import com.zxing.camera.CameraManager;
24 | import com.zxing.decoding.DecodeFormatManager;
25 |
26 | import java.util.Hashtable;
27 | import java.util.Objects;
28 | import java.util.Vector;
29 |
30 | /**
31 | * Created by aaron on 16/7/27.
32 | * 二维码扫描工具类
33 | */
34 | public class CodeUtils {
35 |
36 | public static final String RESULT_TYPE = "result_type";
37 | public static final String RESULT_STRING = "result_string";
38 | public static final int RESULT_SUCCESS = 1;
39 | public static final int RESULT_FAILED = 2;
40 |
41 | public static final String LAYOUT_ID = "layout_id";
42 |
43 |
44 |
45 | /**
46 | * 解析二维码图片工具类
47 | * @param analyzeCallback
48 | */
49 | public static void analyzeBitmap(String path, AnalyzeCallback analyzeCallback) {
50 |
51 | /**
52 | * 首先判断图片的大小,若图片过大,则执行图片的裁剪操作,防止OOM
53 | */
54 | BitmapFactory.Options options = new BitmapFactory.Options();
55 | options.inJustDecodeBounds = true; // 先获取原大小
56 | Bitmap mBitmap = BitmapFactory.decodeFile(path, options);
57 | options.inJustDecodeBounds = false; // 获取新的大小
58 |
59 | int sampleSize = (int) (options.outHeight / (float) 400);
60 |
61 | if (sampleSize <= 0)
62 | sampleSize = 1;
63 | options.inSampleSize = sampleSize;
64 | mBitmap = BitmapFactory.decodeFile(path, options);
65 |
66 | MultiFormatReader multiFormatReader = new MultiFormatReader();
67 |
68 | // 解码的参数
69 | Hashtable hints = new Hashtable(2);
70 | // 可以解析的编码类型
71 | Vector decodeFormats = new Vector();
72 | if (decodeFormats == null || decodeFormats.isEmpty()) {
73 | decodeFormats = new Vector();
74 |
75 | // 这里设置可扫描的类型,我这里选择了都支持
76 | decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS);
77 | decodeFormats.addAll(DecodeFormatManager.QR_CODE_FORMATS);
78 | decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS);
79 | }
80 | hints.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormats);
81 | // 设置继续的字符编码格式为UTF8
82 | // hints.put(DecodeHintType.CHARACTER_SET, "UTF8");
83 | // 设置解析配置参数
84 | multiFormatReader.setHints(hints);
85 |
86 | // 开始对图像资源解码
87 | Result rawResult = null;
88 | try {
89 | rawResult = multiFormatReader.decodeWithState(new BinaryBitmap(new HybridBinarizer(new BitmapLuminanceSource(mBitmap))));
90 | } catch (Exception e) {
91 | e.printStackTrace();
92 | }
93 |
94 | if (rawResult != null) {
95 | if (analyzeCallback != null) {
96 | analyzeCallback.onAnalyzeSuccess(mBitmap, rawResult.getText());
97 | }
98 | } else {
99 | if (analyzeCallback != null) {
100 | analyzeCallback.onAnalyzeFailed();
101 | }
102 | }
103 | }
104 |
105 | /**
106 | * 生成二维码图片
107 | * @param text
108 | * @param w
109 | * @param h
110 | * @param logo
111 | * @return
112 | */
113 | public static Bitmap createImage(String text,int w,int h,Bitmap logo) {
114 | if (TextUtils.isEmpty(text)) {
115 | return null;
116 | }
117 | try {
118 | Bitmap scaleLogo = getScaleLogo(logo,w,h);
119 |
120 | int offsetX = w / 2;
121 | int offsetY = h / 2;
122 |
123 | int scaleWidth = 0;
124 | int scaleHeight = 0;
125 | if (scaleLogo != null) {
126 | scaleWidth = scaleLogo.getWidth();
127 | scaleHeight = scaleLogo.getHeight();
128 | offsetX = (w - scaleWidth) / 2;
129 | offsetY = (h - scaleHeight) / 2;
130 | }
131 | Hashtable hints = new Hashtable();
132 | hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
133 | //容错级别
134 | hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
135 | //设置空白边距的宽度
136 | hints.put(EncodeHintType.MARGIN, 0);
137 | BitMatrix bitMatrix = new QRCodeWriter().encode(text, BarcodeFormat.QR_CODE, w, h, hints);
138 | int[] pixels = new int[w * h];
139 | for (int y = 0; y < h; y++) {
140 | for (int x = 0; x < w; x++) {
141 | if(x >= offsetX && x < offsetX + scaleWidth && y>= offsetY && y < offsetY + scaleHeight){
142 | int pixel = scaleLogo.getPixel(x-offsetX,y-offsetY);
143 | if(pixel == 0){
144 | if(bitMatrix.get(x, y)){
145 | pixel = 0xff000000;
146 | }else{
147 | pixel = 0xffffffff;
148 | }
149 | }
150 | pixels[y * w + x] = pixel;
151 | }else{
152 | if (bitMatrix.get(x, y)) {
153 | pixels[y * w + x] = 0xff000000;
154 | } else {
155 | pixels[y * w + x] = 0xffffffff;
156 | }
157 | }
158 | }
159 | }
160 | Bitmap bitmap = Bitmap.createBitmap(w, h,
161 | Bitmap.Config.ARGB_8888);
162 | bitmap.setPixels(pixels, 0, w, 0, 0, w, h);
163 | return bitmap;
164 | } catch (WriterException e) {
165 | e.printStackTrace();
166 | }
167 | return null;
168 | }
169 |
170 | private static Bitmap getScaleLogo(Bitmap logo,int w,int h){
171 | if(logo == null)return null;
172 | Matrix matrix = new Matrix();
173 | float scaleFactor = Math.min(w * 1.0f / 5 / logo.getWidth(), h * 1.0f / 5 /logo.getHeight());
174 | matrix.postScale(scaleFactor,scaleFactor);
175 | Bitmap result = Bitmap.createBitmap(logo, 0, 0, logo.getWidth(), logo.getHeight(), matrix, true);
176 | return result;
177 | }
178 |
179 | /**
180 | * 解析二维码结果
181 | */
182 | public interface AnalyzeCallback{
183 |
184 | public void onAnalyzeSuccess(Bitmap mBitmap, String result);
185 |
186 | public void onAnalyzeFailed();
187 | }
188 |
189 |
190 | /**
191 | * 为CaptureFragment设置layout参数
192 | * @param captureFragment
193 | * @param layoutId
194 | */
195 | public static void setFragmentArgs(CaptureFragment captureFragment, int layoutId) {
196 | if (captureFragment == null || layoutId == -1) {
197 | return;
198 | }
199 |
200 | Bundle bundle = new Bundle();
201 | bundle.putInt(LAYOUT_ID, layoutId);
202 | captureFragment.setArguments(bundle);
203 | }
204 |
205 | public static void isLightEnable(boolean isEnable) {
206 | if (isEnable) {
207 | Camera camera = CameraManager.get().getCamera();
208 | if (camera != null) {
209 | Camera.Parameters parameter = camera.getParameters();
210 | parameter.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
211 | camera.setParameters(parameter);
212 | }
213 | } else {
214 | Camera camera = CameraManager.get().getCamera();
215 | if (camera != null) {
216 | Camera.Parameters parameter = camera.getParameters();
217 | parameter.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
218 | camera.setParameters(parameter);
219 | }
220 | }
221 | }
222 | }
223 |
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/activity/ScanActivity.java:
--------------------------------------------------------------------------------
1 | package com.zxing.activity;
2 |
3 | import android.Manifest;
4 | import android.annotation.TargetApi;
5 | import android.app.Activity;
6 | import android.content.Context;
7 | import android.content.Intent;
8 | import android.content.pm.PackageManager;
9 | import android.graphics.Bitmap;
10 | import android.hardware.Sensor;
11 | import android.hardware.SensorEvent;
12 | import android.hardware.SensorEventListener;
13 | import android.hardware.SensorManager;
14 | import android.net.Uri;
15 | import android.os.Bundle;
16 | import android.support.annotation.NonNull;
17 | import android.support.annotation.Nullable;
18 | import android.support.v4.app.ActivityCompat;
19 | import android.support.v7.app.AppCompatActivity;
20 | import android.view.View;
21 | import android.view.WindowManager;
22 | import android.view.animation.AlphaAnimation;
23 | import android.widget.LinearLayout;
24 | import android.widget.Toast;
25 |
26 | import com.zxing.R;
27 | import com.zxing.UriUtils;
28 | import com.zxing.camera.CameraManager;
29 |
30 | /**
31 | * @author: winton
32 | * @time: 2018/9/6 下午5:13
33 | * @desc: 描述
34 | */
35 | public class ScanActivity extends AppCompatActivity implements View.OnClickListener{
36 |
37 | private CaptureFragment mFragment;
38 | private CodeUtils.AnalyzeCallback mCallback;
39 | private LinearLayout mLightLayout;
40 |
41 | private boolean isLightOpen = false;
42 |
43 |
44 | private static final int REQ_CAMERA = 0x101;
45 | private static final int REQ_PHOTO = 0x102;
46 | private static final int REQ_CHOOSE_PHOTO = 0x103;
47 |
48 |
49 | public static void start(Activity context,int req){
50 | Intent intent = new Intent(context,ScanActivity.class);
51 | context.startActivityForResult(intent,req);
52 | }
53 |
54 | public static void start(Activity context,int req,boolean needAlbum){
55 | Intent intent = new Intent(context,ScanActivity.class);
56 | intent.putExtra("needAlbum",needAlbum);
57 | context.startActivityForResult(intent,req);
58 | }
59 |
60 |
61 | @Override
62 | protected void onCreate(@Nullable Bundle savedInstanceState) {
63 | super.onCreate(savedInstanceState);
64 | setContentView(R.layout.act_scan);
65 | checkCameraPermission();
66 | initListener();
67 | initData();
68 | }
69 |
70 | private void initListener(){
71 | findViewById(R.id.iv_back).setOnClickListener(this);
72 | boolean needAlbum = getIntent().getBooleanExtra("needAlbum",false);
73 | if(needAlbum){
74 | findViewById(R.id.tv_ablumn).setOnClickListener(this);
75 | findViewById(R.id.tv_ablumn).setVisibility(View.INVISIBLE);
76 | }
77 |
78 |
79 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
80 | checkCameraPermission();
81 | CameraManager.init(getApplicationContext());
82 | SensorManager mSM = (SensorManager) getSystemService(SENSOR_SERVICE);
83 | Sensor mLightSensor = mSM.getDefaultSensor(Sensor.TYPE_LIGHT);
84 | mSM.registerListener(new SensorEventListener() {
85 | @Override
86 | public void onSensorChanged(SensorEvent event) {
87 | //获取光线强度
88 | float lux = event.values[0];
89 | if(lux > 10){
90 | if(!isLightOpen && mLightLayout.getVisibility() == View.VISIBLE){
91 | mLightLayout.setVisibility(View.GONE);
92 | }
93 | }else {
94 | //光线强度小于阈值时,显示电灯开关
95 | if(mLightLayout.getVisibility() != View.VISIBLE){
96 | mLightLayout.setVisibility(View.VISIBLE);
97 | showLightAnim(mLightLayout);
98 | }
99 | }
100 | }
101 | @Override
102 | public void onAccuracyChanged(Sensor sensor, int accuracy) {
103 |
104 | }
105 | },mLightSensor,SensorManager.SENSOR_DELAY_NORMAL);
106 |
107 | }
108 |
109 | /**
110 | * 灯展示出来时动画
111 | * @param view
112 | */
113 | private void showLightAnim(View view){
114 | AlphaAnimation alphaAnimation = new AlphaAnimation(0,1);
115 | alphaAnimation.setDuration(500);
116 | view.startAnimation(alphaAnimation);
117 | }
118 |
119 | private void initData(){
120 | mFragment = new CaptureFragment();
121 | mLightLayout = findViewById(R.id.ll_light);
122 | mLightLayout.setOnClickListener(this);
123 | CodeUtils.setFragmentArgs(mFragment,R.layout.layout_scan);
124 | mCallback = new CodeUtils.AnalyzeCallback() {
125 | @Override
126 | public void onAnalyzeSuccess(Bitmap mBitmap, String result) {
127 | Intent intent= new Intent();
128 | Bundle bundle = new Bundle();
129 | bundle.putInt(CodeUtils.RESULT_TYPE,CodeUtils.RESULT_SUCCESS);
130 | bundle.putString(CodeUtils.RESULT_STRING,result);
131 | intent.putExtras(bundle);
132 | setResult(RESULT_OK,intent);
133 | finish();
134 | }
135 |
136 | @Override
137 | public void onAnalyzeFailed() {
138 | Intent intent= new Intent();
139 | Bundle bundle = new Bundle();
140 | bundle.putInt(CodeUtils.RESULT_TYPE,CodeUtils.RESULT_FAILED);
141 | intent.putExtras(bundle);
142 | setResult(RESULT_OK,intent);
143 | finish();
144 | }
145 | };
146 |
147 | mFragment.setAnalyzeCallback(mCallback);
148 | getSupportFragmentManager().beginTransaction().replace(R.id.fl_my_container,mFragment).commit();
149 | }
150 |
151 | @Override
152 | public void onClick(View v) {
153 | int id = v.getId();
154 | if(id == R.id.iv_back){
155 | this.finish();
156 | return;
157 | }
158 | if(id == R.id.tv_ablumn){
159 | checkAlbumPermission();
160 | return;
161 | }
162 | if(id == R.id.ll_light){
163 | openLight(!isLightOpen);
164 | return;
165 | }
166 | }
167 |
168 | /**
169 | * 控制闪光灯的打开关闭
170 | * @param isLightOpen
171 | */
172 | private void openLight(boolean isLightOpen) {
173 | this.isLightOpen = isLightOpen;
174 | CodeUtils.isLightEnable(isLightOpen);
175 | }
176 |
177 |
178 | @Override
179 | protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
180 | super.onActivityResult(requestCode, resultCode, data);
181 | switch (requestCode){
182 | case REQ_CHOOSE_PHOTO:
183 | if(resultCode == RESULT_OK){
184 | String path = "";
185 | Uri uri = data.getData();
186 | try {
187 | path = UriUtils.getPath(getApplicationContext(),uri);
188 | CodeUtils.analyzeBitmap(path,mCallback);
189 | } catch (Exception e) {
190 | e.printStackTrace();
191 | }
192 | }
193 | break;
194 | default:break;
195 | }
196 | }
197 |
198 | /**
199 | * 检查相机权限
200 | */
201 | @TargetApi(23)
202 | private void checkCameraPermission(){
203 | int code = ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
204 | if(code == PackageManager.PERMISSION_GRANTED){
205 | return;
206 | }
207 | if(shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)){
208 | Toast.makeText(getApplication(),"拒绝此权限将导致功能不可用!",Toast.LENGTH_SHORT).show();
209 | ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA},REQ_CAMERA);
210 | }else {
211 | ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA},REQ_CAMERA);
212 | }
213 | }
214 |
215 | /**
216 | * 查看相册权限
217 | */
218 | @TargetApi(23)
219 | private void checkAlbumPermission(){
220 | int code = ActivityCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE);
221 | if(code == PackageManager.PERMISSION_GRANTED){
222 | choosePhoto();
223 | return;
224 | }
225 | if(shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)){
226 | Toast.makeText(getApplication(),"拒绝此权限将导致功能不可用!",Toast.LENGTH_SHORT).show();
227 | ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},REQ_PHOTO);
228 | }else {
229 | ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},REQ_PHOTO);
230 | }
231 | }
232 |
233 | @Override
234 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
235 | super.onRequestPermissionsResult(requestCode, permissions, grantResults);
236 | switch (requestCode){
237 | case REQ_CAMERA:
238 | break;
239 | case REQ_PHOTO:
240 | if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
241 | choosePhoto();
242 | }
243 | break;
244 | default:
245 | break;
246 | }
247 | }
248 |
249 | /**
250 | * 跳转相册选择
251 | */
252 | private void choosePhoto() {
253 | Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
254 | intent.setType("image/*");
255 | startActivityForResult(intent,REQ_CHOOSE_PHOTO);
256 | }
257 | }
258 |
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/activity/ZXingLibrary.java:
--------------------------------------------------------------------------------
1 | package com.zxing.activity;
2 |
3 | import android.content.Context;
4 | import android.util.DisplayMetrics;
5 |
6 | import com.zxing.DisplayUtil;
7 |
8 |
9 | /**
10 | * Created by aaron on 16/9/7.
11 | */
12 |
13 | public class ZXingLibrary {
14 |
15 | public static void initDisplayOpinion(Context context) {
16 | if (context == null) {
17 | return;
18 | }
19 | DisplayMetrics dm = context.getResources().getDisplayMetrics();
20 | DisplayUtil.density = dm.density;
21 | DisplayUtil.densityDPI = dm.densityDpi;
22 | DisplayUtil.screenWidthPx = dm.widthPixels;
23 | DisplayUtil.screenhightPx = dm.heightPixels;
24 | DisplayUtil.screenWidthDip = DisplayUtil.px2dip(context, dm.widthPixels);
25 | DisplayUtil.screenHightDip = DisplayUtil.px2dip(context, dm.heightPixels);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/camera/AutoFocusCallback.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 ZXing authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.zxing.camera;
18 |
19 | import android.hardware.Camera;
20 | import android.os.Handler;
21 | import android.os.Message;
22 | import android.util.Log;
23 |
24 | public final class AutoFocusCallback implements Camera.AutoFocusCallback {
25 |
26 | private static final String TAG = AutoFocusCallback.class.getSimpleName();
27 |
28 | private static final long AUTOFOCUS_INTERVAL_MS = 1500L;
29 |
30 | private Handler autoFocusHandler;
31 | private int autoFocusMessage;
32 |
33 | public void setHandler(Handler autoFocusHandler, int autoFocusMessage) {
34 | this.autoFocusHandler = autoFocusHandler;
35 | this.autoFocusMessage = autoFocusMessage;
36 | }
37 |
38 | public void onAutoFocus(boolean success, Camera camera) {
39 | if (autoFocusHandler != null) {
40 | Message message = autoFocusHandler.obtainMessage(autoFocusMessage, success);
41 | autoFocusHandler.sendMessageDelayed(message, AUTOFOCUS_INTERVAL_MS);
42 | autoFocusHandler = null;
43 | } else {
44 | Log.d(TAG, "Got auto-focus callback, but no handler for it");
45 | }
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/camera/BitmapLuminanceSource.java:
--------------------------------------------------------------------------------
1 | package com.zxing.camera;
2 |
3 | import android.graphics.Bitmap;
4 |
5 | import com.google.zxing.LuminanceSource;
6 |
7 | /**
8 | * Created by aaron on 16/7/27.
9 | * 自定义解析Bitmap LuminanceSource
10 | */
11 | public class BitmapLuminanceSource extends LuminanceSource {
12 |
13 | private byte bitmapPixels[];
14 |
15 | public BitmapLuminanceSource(Bitmap bitmap) {
16 | super(bitmap.getWidth(), bitmap.getHeight());
17 |
18 | // 首先,要取得该图片的像素数组内容
19 | int[] data = new int[bitmap.getWidth() * bitmap.getHeight()];
20 | this.bitmapPixels = new byte[bitmap.getWidth() * bitmap.getHeight()];
21 | bitmap.getPixels(data, 0, getWidth(), 0, 0, getWidth(), getHeight());
22 |
23 | // 将int数组转换为byte数组,也就是取像素值中蓝色值部分作为辨析内容
24 | for (int i = 0; i < data.length; i++) {
25 | this.bitmapPixels[i] = (byte) data[i];
26 | }
27 | }
28 |
29 | @Override
30 | public byte[] getMatrix() {
31 | // 返回我们生成好的像素数据
32 | return bitmapPixels;
33 | }
34 |
35 | @Override
36 | public byte[] getRow(int y, byte[] row) {
37 | // 这里要得到指定行的像素数据
38 | System.arraycopy(bitmapPixels, y * getWidth(), row, 0, getWidth());
39 | return row;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/camera/CameraConfigurationManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 ZXing authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.zxing.camera;
18 |
19 | import android.content.Context;
20 | import android.graphics.Point;
21 | import android.hardware.Camera;
22 | import android.os.Build;
23 | import android.util.Log;
24 | import android.view.Display;
25 | import android.view.WindowManager;
26 |
27 | import java.util.regex.Pattern;
28 |
29 | final class CameraConfigurationManager {
30 |
31 | private static final String TAG = CameraConfigurationManager.class.getSimpleName();
32 |
33 | private static final int TEN_DESIRED_ZOOM = 27;
34 | private static final int DESIRED_SHARPNESS = 30;
35 |
36 | private static final Pattern COMMA_PATTERN = Pattern.compile(",");
37 |
38 | private final Context context;
39 | private Point screenResolution;
40 | private Point cameraResolution;
41 | private int previewFormat;
42 | private String previewFormatString;
43 |
44 | CameraConfigurationManager(Context context) {
45 | this.context = context;
46 | }
47 |
48 | /**
49 | * Reads, one time, values from the camera that are needed by the app.
50 | */
51 | void initFromCameraParameters(Camera camera) {
52 | Camera.Parameters parameters = camera.getParameters();
53 | previewFormat = parameters.getPreviewFormat();
54 | previewFormatString = parameters.get("preview-format");
55 | Log.d(TAG, "Default preview format: " + previewFormat + '/' + previewFormatString);
56 | WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
57 | Display display = manager.getDefaultDisplay();
58 | screenResolution = new Point(display.getWidth(), display.getHeight());
59 | Log.d(TAG, "Screen resolution: " + screenResolution);
60 |
61 | Point screenResolutionForCamera = new Point();
62 | screenResolutionForCamera.x = screenResolution.x;
63 | screenResolutionForCamera.y = screenResolution.y;
64 | // preview size is always something like 480*320, other 320*480
65 | if (screenResolution.x < screenResolution.y) {
66 | screenResolutionForCamera.x = screenResolution.y;
67 | screenResolutionForCamera.y = screenResolution.x;
68 | }
69 | Log.i("#########", "screenX:" + screenResolutionForCamera.x + " screenY:" + screenResolutionForCamera.y);
70 | cameraResolution = getCameraResolution(parameters, screenResolutionForCamera);
71 |
72 | // cameraResolution = getCameraResolution(parameters, screenResolution);
73 | Log.d(TAG, "Camera resolution: " + screenResolution);
74 | }
75 |
76 | /**
77 | * Sets the camera up to take preview images which are used for both preview and decoding.
78 | * We detect the preview format here so that buildLuminanceSource() can build an appropriate
79 | * LuminanceSource subclass. In the future we may want to force YUV420SP as it's the smallest,
80 | * and the planar Y can be used for barcode scanning without a copy in some cases.
81 | */
82 | void setDesiredCameraParameters(Camera camera) {
83 | Camera.Parameters parameters = camera.getParameters();
84 | Log.d(TAG, "Setting preview size: " + cameraResolution);
85 | parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);
86 | setFlash(parameters);
87 | setZoom(parameters);
88 | //setSharpness(parameters);
89 | //modify here
90 | camera.setDisplayOrientation(90);
91 | camera.setParameters(parameters);
92 | }
93 |
94 | Point getCameraResolution() {
95 | return cameraResolution;
96 | }
97 |
98 | Point getScreenResolution() {
99 | return screenResolution;
100 | }
101 |
102 | int getPreviewFormat() {
103 | return previewFormat;
104 | }
105 |
106 | String getPreviewFormatString() {
107 | return previewFormatString;
108 | }
109 |
110 | private static Point getCameraResolution(Camera.Parameters parameters, Point screenResolution) {
111 |
112 | String previewSizeValueString = parameters.get("preview-size-values");
113 | // saw this on Xperia
114 | if (previewSizeValueString == null) {
115 | previewSizeValueString = parameters.get("preview-size-value");
116 | }
117 |
118 | Point cameraResolution = null;
119 |
120 | if (previewSizeValueString != null) {
121 | Log.d(TAG, "preview-size-values parameter: " + previewSizeValueString);
122 | cameraResolution = findBestPreviewSizeValue(previewSizeValueString, screenResolution);
123 | }
124 |
125 | if (cameraResolution == null) {
126 | // Ensure that the camera resolution is a multiple of 8, as the screen may not be.
127 | cameraResolution = new Point(
128 | (screenResolution.x >> 3) << 3,
129 | (screenResolution.y >> 3) << 3);
130 | }
131 |
132 | return cameraResolution;
133 | }
134 |
135 | private static Point findBestPreviewSizeValue(CharSequence previewSizeValueString, Point screenResolution) {
136 | int bestX = 0;
137 | int bestY = 0;
138 | int diff = Integer.MAX_VALUE;
139 | for (String previewSize : COMMA_PATTERN.split(previewSizeValueString)) {
140 |
141 | previewSize = previewSize.trim();
142 | int dimPosition = previewSize.indexOf('x');
143 | if (dimPosition < 0) {
144 | Log.w(TAG, "Bad preview-size: " + previewSize);
145 | continue;
146 | }
147 |
148 | int newX;
149 | int newY;
150 | try {
151 | newX = Integer.parseInt(previewSize.substring(0, dimPosition));
152 | newY = Integer.parseInt(previewSize.substring(dimPosition + 1));
153 | } catch (NumberFormatException nfe) {
154 | Log.w(TAG, "Bad preview-size: " + previewSize);
155 | continue;
156 | }
157 |
158 | int newDiff = Math.abs(newX - screenResolution.x) + Math.abs(newY - screenResolution.y);
159 | if (newDiff == 0) {
160 | bestX = newX;
161 | bestY = newY;
162 | break;
163 | } else if (newDiff < diff) {
164 | bestX = newX;
165 | bestY = newY;
166 | diff = newDiff;
167 | }
168 |
169 | }
170 |
171 | if (bestX > 0 && bestY > 0) {
172 | return new Point(bestX, bestY);
173 | }
174 | return null;
175 | }
176 |
177 | private static int findBestMotZoomValue(CharSequence stringValues, int tenDesiredZoom) {
178 | int tenBestValue = 0;
179 | for (String stringValue : COMMA_PATTERN.split(stringValues)) {
180 | stringValue = stringValue.trim();
181 | double value;
182 | try {
183 | value = Double.parseDouble(stringValue);
184 | } catch (NumberFormatException nfe) {
185 | return tenDesiredZoom;
186 | }
187 | int tenValue = (int) (10.0 * value);
188 | if (Math.abs(tenDesiredZoom - value) < Math.abs(tenDesiredZoom - tenBestValue)) {
189 | tenBestValue = tenValue;
190 | }
191 | }
192 | return tenBestValue;
193 | }
194 |
195 | private void setFlash(Camera.Parameters parameters) {
196 | // FIXME: This is a hack to turn the flash off on the Samsung Galaxy.
197 | // And this is a hack-hack to work around a different value on the Behold II
198 | // Restrict Behold II check to Cupcake, per Samsung's advice
199 | //if (Build.MODEL.contains("Behold II") &&
200 | // CameraManager.SDK_INT == Build.VERSION_CODES.CUPCAKE) {
201 | if (Build.MODEL.contains("Behold II") && CameraManager.SDK_INT == 3) { // 3 = Cupcake
202 | parameters.set("flash-value", 1);
203 | } else {
204 | parameters.set("flash-value", 2);
205 | }
206 | // This is the standard setting to turn the flash off that all devices should honor.
207 | parameters.set("flash-mode", "off");
208 | }
209 |
210 | private void setZoom(Camera.Parameters parameters) {
211 |
212 | String zoomSupportedString = parameters.get("zoom-supported");
213 | if (zoomSupportedString != null && !Boolean.parseBoolean(zoomSupportedString)) {
214 | return;
215 | }
216 |
217 | int tenDesiredZoom = TEN_DESIRED_ZOOM;
218 |
219 | String maxZoomString = parameters.get("max-zoom");
220 | if (maxZoomString != null) {
221 | try {
222 | int tenMaxZoom = (int) (10.0 * Double.parseDouble(maxZoomString));
223 | if (tenDesiredZoom > tenMaxZoom) {
224 | tenDesiredZoom = tenMaxZoom;
225 | }
226 | } catch (NumberFormatException nfe) {
227 | Log.w(TAG, "Bad max-zoom: " + maxZoomString);
228 | }
229 | }
230 |
231 | String takingPictureZoomMaxString = parameters.get("taking-picture-zoom-max");
232 | if (takingPictureZoomMaxString != null) {
233 | try {
234 | int tenMaxZoom = Integer.parseInt(takingPictureZoomMaxString);
235 | if (tenDesiredZoom > tenMaxZoom) {
236 | tenDesiredZoom = tenMaxZoom;
237 | }
238 | } catch (NumberFormatException nfe) {
239 | Log.w(TAG, "Bad taking-picture-zoom-max: " + takingPictureZoomMaxString);
240 | }
241 | }
242 |
243 | String motZoomValuesString = parameters.get("mot-zoom-values");
244 | if (motZoomValuesString != null) {
245 | tenDesiredZoom = findBestMotZoomValue(motZoomValuesString, tenDesiredZoom);
246 | }
247 |
248 | String motZoomStepString = parameters.get("mot-zoom-step");
249 | if (motZoomStepString != null) {
250 | try {
251 | double motZoomStep = Double.parseDouble(motZoomStepString.trim());
252 | int tenZoomStep = (int) (10.0 * motZoomStep);
253 | if (tenZoomStep > 1) {
254 | tenDesiredZoom -= tenDesiredZoom % tenZoomStep;
255 | }
256 | } catch (NumberFormatException nfe) {
257 | // continue
258 | }
259 | }
260 |
261 | // Set zoom. This helps encourage the user to pull back.
262 | // Some devices like the Behold have a zoom parameter
263 | if (maxZoomString != null || motZoomValuesString != null) {
264 | parameters.set("zoom", String.valueOf(tenDesiredZoom / 10.0));
265 | }
266 |
267 | // Most devices, like the Hero, appear to expose this zoom parameter.
268 | // It takes on values like "27" which appears to mean 2.7x zoom
269 | if (takingPictureZoomMaxString != null) {
270 | parameters.set("taking-picture-zoom", tenDesiredZoom);
271 | }
272 | }
273 |
274 | public static int getDesiredSharpness() {
275 | return DESIRED_SHARPNESS;
276 | }
277 |
278 | }
279 |
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/camera/CameraManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 ZXing authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.zxing.camera;
18 |
19 | import android.content.Context;
20 | import android.graphics.PixelFormat;
21 | import android.graphics.Point;
22 | import android.graphics.Rect;
23 | import android.hardware.Camera;
24 | import android.os.Build;
25 | import android.os.Handler;
26 | import android.view.SurfaceHolder;
27 |
28 | import java.io.IOException;
29 |
30 | /**
31 | * This object wraps the Camera service object and expects to be the only one talking to it. The
32 | * implementation encapsulates the steps needed to take preview-sized images, which are used for
33 | * both preview and decoding.
34 | */
35 | public final class CameraManager {
36 |
37 | private static final String TAG = CameraManager.class.getSimpleName();
38 |
39 | public static int FRAME_WIDTH = -1;
40 | public static int FRAME_HEIGHT = -1;
41 | public static int FRAME_MARGINTOP = -1;
42 |
43 | private static CameraManager cameraManager;
44 |
45 | static final int SDK_INT; // Later we can use Build.VERSION.SDK_INT
46 |
47 | static {
48 | int sdkInt;
49 | try {
50 | sdkInt = Integer.parseInt(Build.VERSION.SDK);
51 | } catch (NumberFormatException nfe) {
52 | // Just to be safe
53 | sdkInt = 10000;
54 | }
55 | SDK_INT = sdkInt;
56 | }
57 |
58 | private final Context context;
59 | private final CameraConfigurationManager configManager;
60 | private Camera camera;
61 | private Rect framingRect;
62 | private Rect framingRectInPreview;
63 | private boolean initialized;
64 | private boolean previewing;
65 | private final boolean useOneShotPreviewCallback;
66 | /**
67 | * Preview frames are delivered here, which we pass on to the registered handler. Make sure to
68 | * clear the handler so it will only receive one message.
69 | */
70 | private final PreviewCallback previewCallback;
71 | /**
72 | * Autofocus callbacks arrive here, and are dispatched to the Handler which requested them.
73 | */
74 | private final AutoFocusCallback autoFocusCallback;
75 |
76 | /**
77 | * Initializes this static object with the Context of the calling Activity.
78 | *
79 | * @param context The Activity which wants to use the camera.
80 | */
81 | public static void init(Context context) {
82 | if (cameraManager == null) {
83 | cameraManager = new CameraManager(context);
84 | }
85 | }
86 |
87 | /**
88 | * Gets the CameraManager singleton instance.
89 | *
90 | * @return A reference to the CameraManager singleton.
91 | */
92 | public static CameraManager get() {
93 | return cameraManager;
94 | }
95 |
96 | private CameraManager(Context context) {
97 |
98 | this.context = context;
99 | this.configManager = new CameraConfigurationManager(context);
100 |
101 | // Camera.setOneShotPreviewCallback() has a race condition in Cupcake, so we use the older
102 | // Camera.setPreviewCallback() on 1.5 and earlier. For Donut and later, we need to use
103 | // the more efficient one shot callback, as the older one can swamp the system and cause it
104 | // to run out of memory. We can't use SDK_INT because it was introduced in the Donut SDK.
105 | //useOneShotPreviewCallback = Integer.parseInt(Build.VERSION.SDK) > Build.VERSION_CODES.CUPCAKE;
106 | useOneShotPreviewCallback = Integer.parseInt(Build.VERSION.SDK) > 3; // 3 = Cupcake
107 |
108 | previewCallback = new PreviewCallback(configManager, useOneShotPreviewCallback);
109 | autoFocusCallback = new AutoFocusCallback();
110 | }
111 |
112 | /**
113 | * Opens the camera driver and initializes the hardware parameters.
114 | *
115 | * @param holder The surface object which the camera will draw preview frames into.
116 | * @throws IOException Indicates the camera driver failed to open.
117 | */
118 | public void openDriver(SurfaceHolder holder) throws IOException {
119 | if (camera == null) {
120 | camera = Camera.open();
121 | if (camera == null) {
122 | throw new IOException();
123 | }
124 | camera.setPreviewDisplay(holder);
125 |
126 | if (!initialized) {
127 | initialized = true;
128 | configManager.initFromCameraParameters(camera);
129 | }
130 | configManager.setDesiredCameraParameters(camera);
131 |
132 | //FIXME
133 | // SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
134 | //�Ƿ�ʹ��ǰ��
135 | // if (prefs.getBoolean(PreferencesActivity.KEY_FRONT_LIGHT, false)) {
136 | // FlashlightManager.enableFlashlight();
137 | // }
138 | FlashlightManager.enableFlashlight();
139 | }
140 | }
141 |
142 | /**
143 | * Closes the camera driver if still in use.
144 | */
145 | public void closeDriver() {
146 | if (camera != null) {
147 | FlashlightManager.disableFlashlight();
148 | camera.release();
149 | camera = null;
150 | }
151 | }
152 |
153 | /**
154 | * Asks the camera hardware to begin drawing preview frames to the screen.
155 | */
156 | public void startPreview() {
157 | if (camera != null && !previewing) {
158 | camera.startPreview();
159 | previewing = true;
160 | }
161 | }
162 |
163 | /**
164 | * Tells the camera to stop drawing preview frames.
165 | */
166 | public void stopPreview() {
167 | if (camera != null && previewing) {
168 | if (!useOneShotPreviewCallback) {
169 | camera.setPreviewCallback(null);
170 | }
171 | camera.stopPreview();
172 | previewCallback.setHandler(null, 0);
173 | autoFocusCallback.setHandler(null, 0);
174 | previewing = false;
175 | }
176 | }
177 |
178 | /**
179 | * A single preview frame will be returned to the handler supplied. The data will arrive as byte[]
180 | * in the message.obj field, with width and height encoded as message.arg1 and message.arg2,
181 | * respectively.
182 | *
183 | * @param handler The handler to send the message to.
184 | * @param message The what field of the message to be sent.
185 | */
186 | public void requestPreviewFrame(Handler handler, int message) {
187 | if (camera != null && previewing) {
188 | previewCallback.setHandler(handler, message);
189 | if (useOneShotPreviewCallback) {
190 | camera.setOneShotPreviewCallback(previewCallback);
191 | } else {
192 | camera.setPreviewCallback(previewCallback);
193 | }
194 | }
195 | }
196 |
197 | /**
198 | * Asks the camera hardware to perform an autofocus.
199 | *
200 | * @param handler The Handler to notify when the autofocus completes.
201 | * @param message The message to deliver.
202 | */
203 | public void requestAutoFocus(Handler handler, int message) {
204 | if (camera != null && previewing) {
205 | autoFocusCallback.setHandler(handler, message);
206 | //Log.d(TAG, "Requesting auto-focus callback");
207 | camera.autoFocus(autoFocusCallback);
208 | }
209 | }
210 |
211 | /**
212 | * Calculates the framing rect which the UI should draw to show the user where to place the
213 | * barcode. This target helps with alignment as well as forces the user to hold the device
214 | * far enough away to ensure the image will be in focus.
215 | *
216 | * @return The rectangle to draw on screen in window coordinates.
217 | */
218 | public Rect getFramingRect() {
219 | try {
220 | Point screenResolution = configManager.getScreenResolution();
221 | // if (framingRect == null) {
222 | if (camera == null) {
223 | return null;
224 | }
225 |
226 | int leftOffset = (screenResolution.x - FRAME_WIDTH) / 2;
227 |
228 | int topOffset;
229 | if (FRAME_MARGINTOP != -1) {
230 | topOffset = FRAME_MARGINTOP;
231 | } else {
232 | topOffset = (screenResolution.y - FRAME_HEIGHT) / 2;
233 | }
234 | framingRect = new Rect(leftOffset, topOffset, leftOffset + FRAME_WIDTH, topOffset + FRAME_HEIGHT);
235 | // }
236 | return framingRect;
237 | } catch (Exception e) {
238 | e.printStackTrace();
239 | return null;
240 | }
241 | }
242 |
243 | /**
244 | * Like {@link #getFramingRect} but coordinates are in terms of the preview frame,
245 | * not UI / screen.
246 | */
247 | public Rect getFramingRectInPreview() {
248 | if (framingRectInPreview == null) {
249 | Rect rect = new Rect(getFramingRect());
250 | Point cameraResolution = configManager.getCameraResolution();
251 | Point screenResolution = configManager.getScreenResolution();
252 | //modify here
253 | // rect.left = rect.left * cameraResolution.x / screenResolution.x;
254 | // rect.right = rect.right * cameraResolution.x / screenResolution.x;
255 | // rect.top = rect.top * cameraResolution.y / screenResolution.y;
256 | // rect.bottom = rect.bottom * cameraResolution.y / screenResolution.y;
257 | rect.left = rect.left * cameraResolution.y / screenResolution.x;
258 | rect.right = rect.right * cameraResolution.y / screenResolution.x;
259 | rect.top = rect.top * cameraResolution.x / screenResolution.y;
260 | rect.bottom = rect.bottom * cameraResolution.x / screenResolution.y;
261 | framingRectInPreview = rect;
262 | }
263 | return framingRectInPreview;
264 | }
265 |
266 | /**
267 | * Converts the result points from still resolution coordinates to screen coordinates.
268 | *
269 | * @param points The points returned by the Reader subclass through Result.getResultPoints().
270 | * @return An array of Points scaled to the size of the framing rect and offset appropriately
271 | * so they can be drawn in screen coordinates.
272 | */
273 | /*
274 | public Point[] convertResultPoints(ResultPoint[] points) {
275 | Rect frame = getFramingRectInPreview();
276 | int count = points.length;
277 | Point[] output = new Point[count];
278 | for (int x = 0; x < count; x++) {
279 | output[x] = new Point();
280 | output[x].x = frame.left + (int) (points[x].getX() + 0.5f);
281 | output[x].y = frame.top + (int) (points[x].getY() + 0.5f);
282 | }
283 | return output;
284 | }
285 | */
286 |
287 | /**
288 | * A factory method to build the appropriate LuminanceSource object based on the format
289 | * of the preview buffers, as described by Camera.Parameters.
290 | *
291 | * @param data A preview frame.
292 | * @param width The width of the image.
293 | * @param height The height of the image.
294 | * @return A PlanarYUVLuminanceSource instance.
295 | */
296 | public PlanarYUVLuminanceSource buildLuminanceSource(byte[] data, int width, int height) {
297 | Rect rect = getFramingRectInPreview();
298 | int previewFormat = configManager.getPreviewFormat();
299 | String previewFormatString = configManager.getPreviewFormatString();
300 | switch (previewFormat) {
301 | // This is the standard Android format which all devices are REQUIRED to support.
302 | // In theory, it's the only one we should ever care about.
303 | case PixelFormat.YCbCr_420_SP:
304 | // This format has never been seen in the wild, but is compatible as we only care
305 | // about the Y channel, so allow it.
306 | case PixelFormat.YCbCr_422_SP:
307 | return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top,
308 | rect.width(), rect.height());
309 | default:
310 | // The Samsung Moment incorrectly uses this variant instead of the 'sp' version.
311 | // Fortunately, it too has all the Y data up front, so we can read it.
312 | if ("yuv420p".equals(previewFormatString)) {
313 | return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top,
314 | rect.width(), rect.height());
315 | }
316 | }
317 | throw new IllegalArgumentException("Unsupported picture format: " +
318 | previewFormat + '/' + previewFormatString);
319 | }
320 |
321 | public Context getContext() {
322 | return context;
323 | }
324 |
325 | public Camera getCamera() {
326 | return camera;
327 | }
328 |
329 | public boolean isPreviewing() {
330 | return previewing;
331 | }
332 |
333 | public boolean isUseOneShotPreviewCallback() {
334 | return useOneShotPreviewCallback;
335 | }
336 |
337 | public PreviewCallback getPreviewCallback() {
338 | return previewCallback;
339 | }
340 |
341 | public AutoFocusCallback getAutoFocusCallback() {
342 | return autoFocusCallback;
343 | }
344 |
345 | public void setPreviewing(boolean previewing) {
346 | this.previewing = previewing;
347 | }
348 | }
349 |
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/camera/FlashlightManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 ZXing authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.zxing.camera;
18 |
19 | import android.os.IBinder;
20 | import android.util.Log;
21 |
22 | import java.lang.reflect.InvocationTargetException;
23 | import java.lang.reflect.Method;
24 |
25 | /**
26 | * This class is used to activate the weak light on some camera phones (not flash)
27 | * in order to illuminate surfaces for scanning. There is no official way to do this,
28 | * but, classes which allow access to this function still exist on some devices.
29 | * This therefore proceeds through a great deal of reflection.
30 | *
31 | * See
32 | * http://almondmendoza.com/2009/01/05/changing-the-screen-brightness-programatically/ and
33 | *
34 | * http://code.google.com/p/droidled/source/browse/trunk/src/com/droidled/demo/DroidLED.java.
35 | * Thanks to Ryan Alford for pointing out the availability of this class.
36 | */
37 | final class FlashlightManager {
38 |
39 | private static final String TAG = FlashlightManager.class.getSimpleName();
40 |
41 | private static final Object iHardwareService;
42 | private static final Method setFlashEnabledMethod;
43 |
44 | static {
45 | iHardwareService = getHardwareService();
46 | setFlashEnabledMethod = getSetFlashEnabledMethod(iHardwareService);
47 | if (iHardwareService == null) {
48 | Log.v(TAG, "This device does supports control of a flashlight");
49 | } else {
50 | Log.v(TAG, "This device does not support control of a flashlight");
51 | }
52 | }
53 |
54 | private FlashlightManager() {
55 | }
56 |
57 | /**
58 | * �����������ƿ���
59 | */
60 | //FIXME
61 | static void enableFlashlight() {
62 | setFlashlight(false);
63 | }
64 |
65 | static void disableFlashlight() {
66 | setFlashlight(false);
67 | }
68 |
69 | private static Object getHardwareService() {
70 | Class> serviceManagerClass = maybeForName("android.os.ServiceManager");
71 | if (serviceManagerClass == null) {
72 | return null;
73 | }
74 |
75 | Method getServiceMethod = maybeGetMethod(serviceManagerClass, "getService", String.class);
76 | if (getServiceMethod == null) {
77 | return null;
78 | }
79 |
80 | Object hardwareService = invoke(getServiceMethod, null, "hardware");
81 | if (hardwareService == null) {
82 | return null;
83 | }
84 |
85 | Class> iHardwareServiceStubClass = maybeForName("android.os.IHardwareService$Stub");
86 | if (iHardwareServiceStubClass == null) {
87 | return null;
88 | }
89 |
90 | Method asInterfaceMethod = maybeGetMethod(iHardwareServiceStubClass, "asInterface", IBinder.class);
91 | if (asInterfaceMethod == null) {
92 | return null;
93 | }
94 |
95 | return invoke(asInterfaceMethod, null, hardwareService);
96 | }
97 |
98 | private static Method getSetFlashEnabledMethod(Object iHardwareService) {
99 | if (iHardwareService == null) {
100 | return null;
101 | }
102 | Class> proxyClass = iHardwareService.getClass();
103 | return maybeGetMethod(proxyClass, "setFlashlightEnabled", boolean.class);
104 | }
105 |
106 | private static Class> maybeForName(String name) {
107 | try {
108 | return Class.forName(name);
109 | } catch (ClassNotFoundException cnfe) {
110 | // OK
111 | return null;
112 | } catch (RuntimeException re) {
113 | Log.w(TAG, "Unexpected error while finding class " + name, re);
114 | return null;
115 | }
116 | }
117 |
118 | private static Method maybeGetMethod(Class> clazz, String name, Class>... argClasses) {
119 | try {
120 | return clazz.getMethod(name, argClasses);
121 | } catch (NoSuchMethodException nsme) {
122 | // OK
123 | return null;
124 | } catch (RuntimeException re) {
125 | Log.w(TAG, "Unexpected error while finding method " + name, re);
126 | return null;
127 | }
128 | }
129 |
130 | private static Object invoke(Method method, Object instance, Object... args) {
131 | try {
132 | return method.invoke(instance, args);
133 | } catch (IllegalAccessException e) {
134 | Log.w(TAG, "Unexpected error while invoking " + method, e);
135 | return null;
136 | } catch (InvocationTargetException e) {
137 | Log.w(TAG, "Unexpected error while invoking " + method, e.getCause());
138 | return null;
139 | } catch (RuntimeException re) {
140 | Log.w(TAG, "Unexpected error while invoking " + method, re);
141 | return null;
142 | }
143 | }
144 |
145 | private static void setFlashlight(boolean active) {
146 | if (iHardwareService != null) {
147 | invoke(setFlashEnabledMethod, iHardwareService, active);
148 | }
149 | }
150 |
151 | }
152 |
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/camera/PlanarYUVLuminanceSource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2009 ZXing authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.zxing.camera;
18 |
19 | import android.graphics.Bitmap;
20 |
21 | import com.google.zxing.LuminanceSource;
22 |
23 | /**
24 | * This object extends LuminanceSource around an array of YUV data returned from the camera driver,
25 | * with the option to crop to a rectangle within the full data. This can be used to exclude
26 | * superfluous pixels around the perimeter and speed up decoding.
27 | *
28 | * It works for any pixel format where the Y channel is planar and appears first, including
29 | * YCbCr_420_SP and YCbCr_422_SP.
30 | *
31 | * @author dswitkin@google.com (Daniel Switkin)
32 | */
33 | public final class PlanarYUVLuminanceSource extends LuminanceSource {
34 | private final byte[] yuvData;
35 | private final int dataWidth;
36 | private final int dataHeight;
37 | private final int left;
38 | private final int top;
39 |
40 | public PlanarYUVLuminanceSource(byte[] yuvData, int dataWidth, int dataHeight, int left, int top,
41 | int width, int height) {
42 | super(width, height);
43 |
44 | if (left + width > dataWidth || top + height > dataHeight) {
45 | throw new IllegalArgumentException("Crop rectangle does not fit within image data.");
46 | }
47 |
48 | this.yuvData = yuvData;
49 | this.dataWidth = dataWidth;
50 | this.dataHeight = dataHeight;
51 | this.left = left;
52 | this.top = top;
53 | }
54 |
55 | @Override
56 | public byte[] getRow(int y, byte[] row) {
57 | if (y < 0 || y >= getHeight()) {
58 | throw new IllegalArgumentException("Requested row is outside the image: " + y);
59 | }
60 | int width = getWidth();
61 | if (row == null || row.length < width) {
62 | row = new byte[width];
63 | }
64 | int offset = (y + top) * dataWidth + left;
65 | System.arraycopy(yuvData, offset, row, 0, width);
66 | return row;
67 | }
68 |
69 | @Override
70 | public byte[] getMatrix() {
71 | int width = getWidth();
72 | int height = getHeight();
73 |
74 | // If the caller asks for the entire underlying image, save the copy and give them the
75 | // original data. The docs specifically warn that result.length must be ignored.
76 | if (width == dataWidth && height == dataHeight) {
77 | return yuvData;
78 | }
79 |
80 | int area = width * height;
81 | byte[] matrix = new byte[area];
82 | int inputOffset = top * dataWidth + left;
83 |
84 | // If the width matches the full width of the underlying data, perform a single copy.
85 | if (width == dataWidth) {
86 | System.arraycopy(yuvData, inputOffset, matrix, 0, area);
87 | return matrix;
88 | }
89 |
90 | // Otherwise copy one cropped row at a time.
91 | byte[] yuv = yuvData;
92 | for (int y = 0; y < height; y++) {
93 | int outputOffset = y * width;
94 | System.arraycopy(yuv, inputOffset, matrix, outputOffset, width);
95 | inputOffset += dataWidth;
96 | }
97 | return matrix;
98 | }
99 |
100 | @Override
101 | public boolean isCropSupported() {
102 | return true;
103 | }
104 |
105 | public int getDataWidth() {
106 | return dataWidth;
107 | }
108 |
109 | public int getDataHeight() {
110 | return dataHeight;
111 | }
112 |
113 | public Bitmap renderCroppedGreyscaleBitmap() {
114 | int width = getWidth();
115 | int height = getHeight();
116 | int[] pixels = new int[width * height];
117 | byte[] yuv = yuvData;
118 | int inputOffset = top * dataWidth + left;
119 |
120 | for (int y = 0; y < height; y++) {
121 | int outputOffset = y * width;
122 | for (int x = 0; x < width; x++) {
123 | int grey = yuv[inputOffset + x] & 0xff;
124 | pixels[outputOffset + x] = 0xFF000000 | (grey * 0x00010101);
125 | }
126 | inputOffset += dataWidth;
127 | }
128 |
129 | Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
130 | bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
131 | return bitmap;
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/camera/PreviewCallback.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 ZXing authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.zxing.camera;
18 |
19 | import android.graphics.Point;
20 | import android.hardware.Camera;
21 | import android.os.Handler;
22 | import android.os.Message;
23 | import android.util.Log;
24 |
25 | public final class PreviewCallback implements Camera.PreviewCallback {
26 |
27 | private static final String TAG = PreviewCallback.class.getSimpleName();
28 |
29 | private final CameraConfigurationManager configManager;
30 | private final boolean useOneShotPreviewCallback;
31 | private Handler previewHandler;
32 | private int previewMessage;
33 |
34 | PreviewCallback(CameraConfigurationManager configManager, boolean useOneShotPreviewCallback) {
35 | this.configManager = configManager;
36 | this.useOneShotPreviewCallback = useOneShotPreviewCallback;
37 | }
38 |
39 | public void setHandler(Handler previewHandler, int previewMessage) {
40 | this.previewHandler = previewHandler;
41 | this.previewMessage = previewMessage;
42 | }
43 |
44 | public void onPreviewFrame(byte[] data, Camera camera) {
45 | Point cameraResolution = configManager.getCameraResolution();
46 | if (!useOneShotPreviewCallback) {
47 | camera.setPreviewCallback(null);
48 | }
49 | if (previewHandler != null) {
50 | Message message = previewHandler.obtainMessage(previewMessage, cameraResolution.x,
51 | cameraResolution.y, data);
52 | message.sendToTarget();
53 | previewHandler = null;
54 | } else {
55 | Log.d(TAG, "Got preview callback, but no handler for it");
56 | }
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/decoding/CaptureActivityHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 ZXing authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.zxing.decoding;
18 |
19 | import android.app.Activity;
20 | import android.content.Intent;
21 | import android.graphics.Bitmap;
22 | import android.net.Uri;
23 | import android.os.Bundle;
24 | import android.os.Handler;
25 | import android.os.Message;
26 | import android.util.Log;
27 |
28 | import com.google.zxing.BarcodeFormat;
29 | import com.google.zxing.Result;
30 | import com.zxing.R;
31 | import com.zxing.activity.CaptureFragment;
32 | import com.zxing.camera.CameraManager;
33 | import com.zxing.view.ViewfinderResultPointCallback;
34 | import com.zxing.view.ViewfinderView;
35 |
36 | import java.util.Vector;
37 |
38 | /**
39 | * This class handles all the messaging which comprises the state machine for capture.
40 | */
41 | public final class CaptureActivityHandler extends Handler {
42 |
43 | private static final String TAG = CaptureActivityHandler.class.getSimpleName();
44 |
45 | private final CaptureFragment fragment;
46 | private final DecodeThread decodeThread;
47 | private State state;
48 |
49 | private enum State {
50 | PREVIEW,
51 | SUCCESS,
52 | DONE
53 | }
54 |
55 | public CaptureActivityHandler(CaptureFragment fragment, Vector decodeFormats,
56 | String characterSet, ViewfinderView viewfinderView) {
57 | this.fragment = fragment;
58 | decodeThread = new DecodeThread(fragment, decodeFormats, characterSet,
59 | new ViewfinderResultPointCallback(viewfinderView));
60 | decodeThread.start();
61 | state = State.SUCCESS;
62 | // Start ourselves capturing previews and decoding.
63 | CameraManager.get().startPreview();
64 | restartPreviewAndDecode();
65 | }
66 |
67 | @Override
68 | public void handleMessage(Message message) {
69 | if (message.what == R.id.auto_focus) {
70 | //Log.d(TAG, "Got auto-focus message");
71 | // When one auto focus pass finishes, start another. This is the closest thing to
72 | // continuous AF. It does seem to hunt a bit, but I'm not sure what else to do.
73 | if (state == State.PREVIEW) {
74 | CameraManager.get().requestAutoFocus(this, R.id.auto_focus);
75 | }
76 | } else if (message.what == R.id.restart_preview) {
77 | Log.d(TAG, "Got restart preview message");
78 | restartPreviewAndDecode();
79 | } else if (message.what == R.id.decode_succeeded) {
80 | Log.d(TAG, "Got decode succeeded message");
81 | state = State.SUCCESS;
82 | Bundle bundle = message.getData();
83 |
84 | /***********************************************************************/
85 | Bitmap barcode = bundle == null ? null :
86 | (Bitmap) bundle.getParcelable(DecodeThread.BARCODE_BITMAP);//���ñ����߳�
87 |
88 | fragment.handleDecode((Result) message.obj, barcode);//���ؽ��
89 | /***********************************************************************/
90 | } else if (message.what == R.id.decode_failed) {
91 | // We're decoding as fast as possible, so when one decode fails, start another.
92 | state = State.PREVIEW;
93 | CameraManager.get().requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
94 | } else if (message.what == R.id.return_scan_result) {
95 | Log.d(TAG, "Got return scan result message");
96 | fragment.getActivity().setResult(Activity.RESULT_OK, (Intent) message.obj);
97 | fragment.getActivity().finish();
98 | } else if (message.what == R.id.launch_product_query) {
99 | Log.d(TAG, "Got product query message");
100 | String url = (String) message.obj;
101 | Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
102 | intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
103 | fragment.getActivity().startActivity(intent);
104 | }
105 | }
106 |
107 | public void quitSynchronously() {
108 | state = State.DONE;
109 | CameraManager.get().stopPreview();
110 | Message quit = Message.obtain(decodeThread.getHandler(), R.id.quit);
111 | quit.sendToTarget();
112 | try {
113 | decodeThread.join();
114 | } catch (InterruptedException e) {
115 | // continue
116 | }
117 |
118 | // Be absolutely sure we don't send any queued up messages
119 | removeMessages(R.id.decode_succeeded);
120 | removeMessages(R.id.decode_failed);
121 | }
122 |
123 | private void restartPreviewAndDecode() {
124 | if (state == State.SUCCESS) {
125 | state = State.PREVIEW;
126 | CameraManager.get().requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
127 | CameraManager.get().requestAutoFocus(this, R.id.auto_focus);
128 | fragment.drawViewfinder();
129 | }
130 | }
131 |
132 | }
133 |
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/decoding/DecodeFormatManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 ZXing authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.zxing.decoding;
18 |
19 | import android.content.Intent;
20 | import android.net.Uri;
21 |
22 | import com.google.zxing.BarcodeFormat;
23 |
24 | import java.util.Arrays;
25 | import java.util.List;
26 | import java.util.Vector;
27 | import java.util.regex.Pattern;
28 |
29 | public class DecodeFormatManager {
30 |
31 | private static final Pattern COMMA_PATTERN = Pattern.compile(",");
32 |
33 | public static final Vector PRODUCT_FORMATS;
34 | public static final Vector ONE_D_FORMATS;
35 | public static final Vector QR_CODE_FORMATS;
36 | public static final Vector DATA_MATRIX_FORMATS;
37 |
38 | static {
39 | PRODUCT_FORMATS = new Vector(5);
40 | PRODUCT_FORMATS.add(BarcodeFormat.UPC_A);
41 | PRODUCT_FORMATS.add(BarcodeFormat.UPC_E);
42 | PRODUCT_FORMATS.add(BarcodeFormat.EAN_13);
43 | PRODUCT_FORMATS.add(BarcodeFormat.EAN_8);
44 | // PRODUCT_FORMATS.add(BarcodeFormat.RSS14);
45 | ONE_D_FORMATS = new Vector(PRODUCT_FORMATS.size() + 4);
46 | ONE_D_FORMATS.addAll(PRODUCT_FORMATS);
47 | ONE_D_FORMATS.add(BarcodeFormat.CODE_39);
48 | ONE_D_FORMATS.add(BarcodeFormat.CODE_93);
49 | ONE_D_FORMATS.add(BarcodeFormat.CODE_128);
50 | ONE_D_FORMATS.add(BarcodeFormat.ITF);
51 | QR_CODE_FORMATS = new Vector(1);
52 | QR_CODE_FORMATS.add(BarcodeFormat.QR_CODE);
53 | DATA_MATRIX_FORMATS = new Vector(1);
54 | DATA_MATRIX_FORMATS.add(BarcodeFormat.DATA_MATRIX);
55 | }
56 |
57 | private DecodeFormatManager() {
58 | }
59 |
60 | static Vector parseDecodeFormats(Intent intent) {
61 | List scanFormats = null;
62 | String scanFormatsString = intent.getStringExtra(Intents.Scan.SCAN_FORMATS);
63 | if (scanFormatsString != null) {
64 | scanFormats = Arrays.asList(COMMA_PATTERN.split(scanFormatsString));
65 | }
66 | return parseDecodeFormats(scanFormats, intent.getStringExtra(Intents.Scan.MODE));
67 | }
68 |
69 | static Vector parseDecodeFormats(Uri inputUri) {
70 | List formats = inputUri.getQueryParameters(Intents.Scan.SCAN_FORMATS);
71 | if (formats != null && formats.size() == 1 && formats.get(0) != null) {
72 | formats = Arrays.asList(COMMA_PATTERN.split(formats.get(0)));
73 | }
74 | return parseDecodeFormats(formats, inputUri.getQueryParameter(Intents.Scan.MODE));
75 | }
76 |
77 | private static Vector parseDecodeFormats(Iterable scanFormats,
78 | String decodeMode) {
79 | if (scanFormats != null) {
80 | Vector formats = new Vector();
81 | try {
82 | for (String format : scanFormats) {
83 | formats.add(BarcodeFormat.valueOf(format));
84 | }
85 | return formats;
86 | } catch (IllegalArgumentException iae) {
87 | // ignore it then
88 | }
89 | }
90 | if (decodeMode != null) {
91 | if (Intents.Scan.PRODUCT_MODE.equals(decodeMode)) {
92 | return PRODUCT_FORMATS;
93 | }
94 | if (Intents.Scan.QR_CODE_MODE.equals(decodeMode)) {
95 | return QR_CODE_FORMATS;
96 | }
97 | if (Intents.Scan.DATA_MATRIX_MODE.equals(decodeMode)) {
98 | return DATA_MATRIX_FORMATS;
99 | }
100 | if (Intents.Scan.ONE_D_MODE.equals(decodeMode)) {
101 | return ONE_D_FORMATS;
102 | }
103 | }
104 | return null;
105 | }
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/decoding/DecodeHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 ZXing authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.zxing.decoding;
18 |
19 | import android.os.Bundle;
20 | import android.os.Handler;
21 | import android.os.Looper;
22 | import android.os.Message;
23 | import android.util.Log;
24 |
25 | import com.google.zxing.BinaryBitmap;
26 | import com.google.zxing.DecodeHintType;
27 | import com.google.zxing.MultiFormatReader;
28 | import com.google.zxing.ReaderException;
29 | import com.google.zxing.Result;
30 | import com.google.zxing.common.HybridBinarizer;
31 | import com.zxing.R;
32 | import com.zxing.activity.CaptureFragment;
33 | import com.zxing.camera.CameraManager;
34 | import com.zxing.camera.PlanarYUVLuminanceSource;
35 |
36 | import java.util.Hashtable;
37 |
38 | final class DecodeHandler extends Handler {
39 |
40 | private static final String TAG = DecodeHandler.class.getSimpleName();
41 |
42 | private final CaptureFragment fragment;
43 | private final MultiFormatReader multiFormatReader;
44 |
45 | DecodeHandler(CaptureFragment fragment, Hashtable hints) {
46 | multiFormatReader = new MultiFormatReader();
47 | multiFormatReader.setHints(hints);
48 | this.fragment = fragment;
49 | }
50 |
51 | @Override
52 | public void handleMessage(Message message) {
53 | if (message.what == R.id.decode) {
54 | decode((byte[]) message.obj, message.arg1, message.arg2);
55 | } else if (message.what == R.id.quit) {
56 | Looper.myLooper().quit();
57 | }
58 | }
59 |
60 | /**
61 | * Decode the data within the viewfinder rectangle, and time how long it took. For efficiency,
62 | * reuse the same reader objects from one decode to the next.
63 | *
64 | * @param data The YUV preview frame.
65 | * @param width The width of the preview frame.
66 | * @param height The height of the preview frame.
67 | */
68 | private void decode(byte[] data, int width, int height) {
69 | long start = System.currentTimeMillis();
70 | Result rawResult = null;
71 |
72 | //modify here
73 | byte[] rotatedData = new byte[data.length];
74 | for (int y = 0; y < height; y++) {
75 | for (int x = 0; x < width; x++)
76 | rotatedData[x * height + height - y - 1] = data[x + y * width];
77 | }
78 | int tmp = width; // Here we are swapping, that's the difference to #11
79 | width = height;
80 | height = tmp;
81 |
82 | PlanarYUVLuminanceSource source = CameraManager.get().buildLuminanceSource(rotatedData, width, height);
83 | BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
84 | try {
85 | rawResult = multiFormatReader.decodeWithState(bitmap);
86 | } catch (ReaderException re) {
87 | // continue
88 | } finally {
89 | multiFormatReader.reset();
90 | }
91 |
92 | if (rawResult != null) {
93 | long end = System.currentTimeMillis();
94 | Log.d(TAG, "Found barcode (" + (end - start) + " ms):\n" + rawResult.toString());
95 | Message message = Message.obtain(fragment.getHandler(), R.id.decode_succeeded, rawResult);
96 | Bundle bundle = new Bundle();
97 | bundle.putParcelable(DecodeThread.BARCODE_BITMAP, source.renderCroppedGreyscaleBitmap());
98 | message.setData(bundle);
99 | //Log.d(TAG, "Sending decode succeeded message...");
100 | message.sendToTarget();
101 | } else {
102 | Message message = Message.obtain(fragment.getHandler(), R.id.decode_failed);
103 | message.sendToTarget();
104 | }
105 | }
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/decoding/DecodeThread.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 ZXing authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.zxing.decoding;
18 |
19 | import android.os.Handler;
20 | import android.os.Looper;
21 |
22 | import com.google.zxing.BarcodeFormat;
23 | import com.google.zxing.DecodeHintType;
24 | import com.google.zxing.ResultPointCallback;
25 | import com.zxing.activity.CaptureFragment;
26 |
27 | import java.util.Hashtable;
28 | import java.util.Vector;
29 | import java.util.concurrent.CountDownLatch;
30 |
31 | /**
32 | * This thread does all the heavy lifting of decoding the images.
33 | * �����߳�
34 | */
35 | final class DecodeThread extends Thread {
36 |
37 | public static final String BARCODE_BITMAP = "barcode_bitmap";
38 | private final CaptureFragment fragment;
39 | private final Hashtable hints;
40 | private Handler handler;
41 | private final CountDownLatch handlerInitLatch;
42 |
43 | DecodeThread(CaptureFragment fragment,
44 | Vector decodeFormats,
45 | String characterSet,
46 | ResultPointCallback resultPointCallback) {
47 |
48 | this.fragment = fragment;
49 | handlerInitLatch = new CountDownLatch(1);
50 |
51 | hints = new Hashtable(3);
52 |
53 | if (decodeFormats == null || decodeFormats.isEmpty()) {
54 | decodeFormats = new Vector();
55 | decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS);
56 | decodeFormats.addAll(DecodeFormatManager.QR_CODE_FORMATS);
57 | decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS);
58 | }
59 |
60 | hints.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormats);
61 |
62 | if (characterSet != null) {
63 | hints.put(DecodeHintType.CHARACTER_SET, characterSet);
64 | }
65 |
66 | hints.put(DecodeHintType.NEED_RESULT_POINT_CALLBACK, resultPointCallback);
67 | }
68 |
69 | Handler getHandler() {
70 | try {
71 | handlerInitLatch.await();
72 | } catch (InterruptedException ie) {
73 | // continue?
74 | }
75 | return handler;
76 | }
77 |
78 | @Override
79 | public void run() {
80 | Looper.prepare();
81 | handler = new DecodeHandler(fragment, hints);
82 | handlerInitLatch.countDown();
83 | Looper.loop();
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/decoding/FinishListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 ZXing authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.zxing.decoding;
18 |
19 | import android.app.Activity;
20 | import android.content.DialogInterface;
21 |
22 | /**
23 | * Simple listener used to exit the app in a few cases.
24 | */
25 | public final class FinishListener
26 | implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener, Runnable {
27 |
28 | private final Activity activityToFinish;
29 |
30 | public FinishListener(Activity activityToFinish) {
31 | this.activityToFinish = activityToFinish;
32 | }
33 |
34 | public void onCancel(DialogInterface dialogInterface) {
35 | run();
36 | }
37 |
38 | public void onClick(DialogInterface dialogInterface, int i) {
39 | run();
40 | }
41 |
42 | public void run() {
43 | activityToFinish.finish();
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/decoding/InactivityTimer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 ZXing authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.zxing.decoding;
18 |
19 | import android.app.Activity;
20 |
21 | import java.util.concurrent.Executors;
22 | import java.util.concurrent.ScheduledExecutorService;
23 | import java.util.concurrent.ScheduledFuture;
24 | import java.util.concurrent.ThreadFactory;
25 | import java.util.concurrent.TimeUnit;
26 |
27 | /**
28 | * Finishes an activity after a period of inactivity.
29 | */
30 | public final class InactivityTimer {
31 |
32 | private static final int INACTIVITY_DELAY_SECONDS = 5 * 60;
33 |
34 | private final ScheduledExecutorService inactivityTimer =
35 | Executors.newSingleThreadScheduledExecutor(new DaemonThreadFactory());
36 | private final Activity activity;
37 | private ScheduledFuture> inactivityFuture = null;
38 |
39 | public InactivityTimer(Activity activity) {
40 | this.activity = activity;
41 | onActivity();
42 | }
43 |
44 | public void onActivity() {
45 | cancel();
46 | inactivityFuture = inactivityTimer.schedule(new FinishListener(activity),
47 | INACTIVITY_DELAY_SECONDS,
48 | TimeUnit.SECONDS);
49 | }
50 |
51 | private void cancel() {
52 | if (inactivityFuture != null) {
53 | inactivityFuture.cancel(true);
54 | inactivityFuture = null;
55 | }
56 | }
57 |
58 | public void shutdown() {
59 | cancel();
60 | inactivityTimer.shutdown();
61 | }
62 |
63 | private static final class DaemonThreadFactory implements ThreadFactory {
64 | public Thread newThread(Runnable runnable) {
65 | Thread thread = new Thread(runnable);
66 | thread.setDaemon(true);
67 | return thread;
68 | }
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/decoding/Intents.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 ZXing authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.zxing.decoding;
18 |
19 | /**
20 | * This class provides the constants to use when sending an Intent to Barcode Scanner.
21 | * These strings are effectively API and cannot be changed.
22 | */
23 | public final class Intents {
24 | private Intents() {
25 | }
26 |
27 | public static final class Scan {
28 | /**
29 | * Send this intent to open the Barcodes app in scanning mode, find a barcode, and return
30 | * the results.
31 | */
32 | public static final String ACTION = "com.google.zxing.client.android.SCAN";
33 |
34 | /**
35 | * By default, sending Scan.ACTION will decode all barcodes that we understand. However it
36 | * may be useful to limit scanning to certain formats. Use Intent.putExtra(MODE, value) with
37 | * one of the values below ({@link #PRODUCT_MODE}, {@link #ONE_D_MODE}, {@link #QR_CODE_MODE}).
38 | * Optional.
39 | *
40 | * Setting this is effectively shorthnad for setting explicit formats with {@link #SCAN_FORMATS}.
41 | * It is overridden by that setting.
42 | */
43 | public static final String MODE = "SCAN_MODE";
44 |
45 | /**
46 | * Comma-separated list of formats to scan for. The values must match the names of
47 | * {@link com.google.zxing.BarcodeFormat}s, such as {@link com.google.zxing.BarcodeFormat#EAN_13}.
48 | * Example: "EAN_13,EAN_8,QR_CODE"
49 | *
50 | * This overrides {@link #MODE}.
51 | */
52 | public static final String SCAN_FORMATS = "SCAN_FORMATS";
53 |
54 | /**
55 | * @see com.google.zxing.DecodeHintType#CHARACTER_SET
56 | */
57 | public static final String CHARACTER_SET = "CHARACTER_SET";
58 |
59 | /**
60 | * Decode only UPC and EAN barcodes. This is the right choice for shopping apps which get
61 | * prices, reviews, etc. for products.
62 | */
63 | public static final String PRODUCT_MODE = "PRODUCT_MODE";
64 |
65 | /**
66 | * Decode only 1D barcodes (currently UPC, EAN, Code 39, and Code 128).
67 | */
68 | public static final String ONE_D_MODE = "ONE_D_MODE";
69 |
70 | /**
71 | * Decode only QR codes.
72 | */
73 | public static final String QR_CODE_MODE = "QR_CODE_MODE";
74 |
75 | /**
76 | * Decode only Data Matrix codes.
77 | */
78 | public static final String DATA_MATRIX_MODE = "DATA_MATRIX_MODE";
79 |
80 | /**
81 | * If a barcode is found, Barcodes returns RESULT_OK to onActivityResult() of the app which
82 | * requested the scan via startSubActivity(). The barcodes contents can be retrieved with
83 | * intent.getStringExtra(RESULT). If the user presses Back, the result code will be
84 | * RESULT_CANCELED.
85 | */
86 | public static final String RESULT = "SCAN_RESULT";
87 |
88 | /**
89 | * Call intent.getStringExtra(RESULT_FORMAT) to determine which barcode format was found.
90 | * See Contents.Format for possible values.
91 | */
92 | public static final String RESULT_FORMAT = "SCAN_RESULT_FORMAT";
93 |
94 | /**
95 | * Setting this to false will not save scanned codes in the history.
96 | */
97 | public static final String SAVE_HISTORY = "SAVE_HISTORY";
98 |
99 | private Scan() {
100 | }
101 | }
102 |
103 | public static final class Encode {
104 | /**
105 | * Send this intent to encode a piece of data as a QR code and display it full screen, so
106 | * that another person can scan the barcode from your screen.
107 | */
108 | public static final String ACTION = "com.google.zxing.client.android.ENCODE";
109 |
110 | /**
111 | * The data to encode. Use Intent.putExtra(DATA, data) where data is either a String or a
112 | * Bundle, depending on the type and format specified. Non-QR Code formats should
113 | * just use a String here. For QR Code, see Contents for details.
114 | */
115 | public static final String DATA = "ENCODE_DATA";
116 |
117 | /**
118 | * The type of data being supplied if the format is QR Code. Use
119 | * Intent.putExtra(TYPE, type) with one of Contents.Type.
120 | */
121 | public static final String TYPE = "ENCODE_TYPE";
122 |
123 | /**
124 | * The barcode format to be displayed. If this isn't specified or is blank,
125 | * it defaults to QR Code. Use Intent.putExtra(FORMAT, format), where
126 | * format is one of Contents.Format.
127 | */
128 | public static final String FORMAT = "ENCODE_FORMAT";
129 |
130 | private Encode() {
131 | }
132 | }
133 |
134 | public static final class SearchBookContents {
135 | /**
136 | * Use Google Book Search to search the contents of the book provided.
137 | */
138 | public static final String ACTION = "com.google.zxing.client.android.SEARCH_BOOK_CONTENTS";
139 |
140 | /**
141 | * The book to search, identified by ISBN number.
142 | */
143 | public static final String ISBN = "ISBN";
144 |
145 | /**
146 | * An optional field which is the text to search for.
147 | */
148 | public static final String QUERY = "QUERY";
149 |
150 | private SearchBookContents() {
151 | }
152 | }
153 |
154 | public static final class WifiConnect {
155 | /**
156 | * Internal intent used to trigger connection to a wi-fi network.
157 | */
158 | public static final String ACTION = "com.google.zxing.client.android.WIFI_CONNECT";
159 |
160 | /**
161 | * The network to connect to, all the configuration provided here.
162 | */
163 | public static final String SSID = "SSID";
164 |
165 | /**
166 | * The network to connect to, all the configuration provided here.
167 | */
168 | public static final String TYPE = "TYPE";
169 |
170 | /**
171 | * The network to connect to, all the configuration provided here.
172 | */
173 | public static final String PASSWORD = "PASSWORD";
174 |
175 | private WifiConnect() {
176 | }
177 | }
178 |
179 |
180 | public static final class Share {
181 | /**
182 | * Give the user a choice of items to encode as a barcode, then render it as a QR Code and
183 | * display onscreen for a friend to scan with their phone.
184 | */
185 | public static final String ACTION = "com.google.zxing.client.android.SHARE";
186 |
187 | private Share() {
188 | }
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/encoding/EncodingHandler.java:
--------------------------------------------------------------------------------
1 | package com.zxing.encoding;
2 |
3 | import android.graphics.Bitmap;
4 |
5 | import com.google.zxing.BarcodeFormat;
6 | import com.google.zxing.EncodeHintType;
7 | import com.google.zxing.MultiFormatWriter;
8 | import com.google.zxing.WriterException;
9 | import com.google.zxing.common.BitMatrix;
10 |
11 | import java.util.Hashtable;
12 |
13 | /**
14 | * @author Ryan Tang
15 | */
16 | public final class EncodingHandler {
17 | private static final int BLACK = 0xff000000;
18 |
19 | public static Bitmap createQRCode(String str, int widthAndHeight) throws WriterException {
20 | Hashtable hints = new Hashtable();
21 | hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
22 | BitMatrix matrix = new MultiFormatWriter().encode(str,
23 | BarcodeFormat.QR_CODE, widthAndHeight, widthAndHeight);
24 | int width = matrix.getWidth();
25 | int height = matrix.getHeight();
26 | int[] pixels = new int[width * height];
27 |
28 | for (int y = 0; y < height; y++) {
29 | for (int x = 0; x < width; x++) {
30 | if (matrix.get(x, y)) {
31 | pixels[y * width + x] = BLACK;
32 | }
33 | }
34 | }
35 | Bitmap bitmap = Bitmap.createBitmap(width, height,
36 | Bitmap.Config.ARGB_8888);
37 | bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
38 | return bitmap;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/view/ViewfinderResultPointCallback.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2009 ZXing authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.zxing.view;
18 |
19 | import com.google.zxing.ResultPoint;
20 | import com.google.zxing.ResultPointCallback;
21 |
22 | public final class ViewfinderResultPointCallback implements ResultPointCallback {
23 |
24 | private final ViewfinderView viewfinderView;
25 |
26 | public ViewfinderResultPointCallback(ViewfinderView viewfinderView) {
27 | this.viewfinderView = viewfinderView;
28 | }
29 |
30 | public void foundPossibleResultPoint(ResultPoint point) {
31 | viewfinderView.addPossibleResultPoint(point);
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/zxing/src/main/java/com/zxing/view/ViewfinderView.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 ZXing authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.zxing.view;
18 |
19 | import android.animation.ValueAnimator;
20 | import android.content.Context;
21 | import android.content.res.Resources;
22 | import android.content.res.TypedArray;
23 | import android.graphics.Bitmap;
24 | import android.graphics.BitmapFactory;
25 | import android.graphics.Canvas;
26 | import android.graphics.Color;
27 | import android.graphics.Paint;
28 | import android.graphics.Rect;
29 | import android.graphics.drawable.Drawable;
30 | import android.util.AttributeSet;
31 | import android.view.View;
32 |
33 | import com.google.zxing.ResultPoint;
34 | import com.zxing.DisplayUtil;
35 | import com.zxing.R;
36 | import com.zxing.camera.CameraManager;
37 |
38 | import java.util.Collection;
39 | import java.util.HashSet;
40 |
41 | /**
42 | * 自定义组件实现,扫描功能
43 | */
44 | public final class ViewfinderView extends View {
45 |
46 | private static final long ANIMATION_DELAY = 10L;
47 | private static final int OPAQUE = 0xFF;
48 |
49 | private final Paint paint;
50 | private Bitmap resultBitmap;
51 | private final int maskColor;
52 | private final int resultColor;
53 | private final int resultPointColor;
54 | private Collection possibleResultPoints;
55 | private Collection lastPossibleResultPoints;
56 |
57 | public ViewfinderView(Context context) {
58 | this(context, null);
59 | }
60 |
61 | public ViewfinderView(Context context, AttributeSet attrs) {
62 | this(context, attrs, -1);
63 |
64 | }
65 | public ViewfinderView(Context context, AttributeSet attrs, int defStyleAttr) {
66 | super(context, attrs, defStyleAttr);
67 | paint = new Paint();
68 | Resources resources = getResources();
69 | maskColor = resources.getColor(R.color.viewfinder_mask);
70 | resultColor = resources.getColor(R.color.result_view);
71 | resultPointColor = resources.getColor(R.color.possible_result_points);
72 | possibleResultPoints = new HashSet<>(5);
73 | scanLight = BitmapFactory.decodeResource(resources, R.drawable.scan_light);
74 | initInnerRect(context, attrs);
75 | }
76 |
77 | /**
78 | * 初始化内部框的大小
79 | *
80 | * @param context
81 | * @param attrs
82 | */
83 | private void initInnerRect(Context context, AttributeSet attrs) {
84 | TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ViewfinderView);
85 |
86 | // 扫描框距离顶部
87 | float innerMarginTop = ta.getDimension(R.styleable.ViewfinderView_inner_margintop, -1);
88 | if (innerMarginTop != -1) {
89 | CameraManager.FRAME_MARGINTOP = (int) innerMarginTop;
90 | }
91 |
92 | // 扫描框的宽度
93 | CameraManager.FRAME_WIDTH = (int) ta.getDimension(R.styleable.ViewfinderView_inner_width, DisplayUtil.screenWidthPx / 2);
94 |
95 | // 扫描框的高度
96 | CameraManager.FRAME_HEIGHT = (int) ta.getDimension(R.styleable.ViewfinderView_inner_height, DisplayUtil.screenWidthPx / 2);
97 |
98 | // 扫描框边角颜色
99 | innercornercolor = ta.getColor(R.styleable.ViewfinderView_inner_corner_color, Color.parseColor("#45DDDD"));
100 | // 扫描框边角长度
101 | innercornerlength = (int) ta.getDimension(R.styleable.ViewfinderView_inner_corner_length, 65);
102 | // 扫描框边角宽度
103 | innercornerwidth = (int) ta.getDimension(R.styleable.ViewfinderView_inner_corner_width, 15);
104 |
105 | // 扫描bitmap
106 | Drawable drawable = ta.getDrawable(R.styleable.ViewfinderView_inner_scan_bitmap);
107 | if (drawable != null) {
108 | }
109 |
110 | // 扫描控件
111 | scanLight = BitmapFactory.decodeResource(getResources(), ta.getResourceId(R.styleable.ViewfinderView_inner_scan_bitmap, R.drawable.scan_light));
112 | // 扫描速度
113 | SCAN_VELOCITY = ta.getInt(R.styleable.ViewfinderView_inner_scan_speed, 5);
114 |
115 | isCircle = ta.getBoolean(R.styleable.ViewfinderView_inner_scan_iscircle, true);
116 |
117 | ta.recycle();
118 | }
119 |
120 | @Override
121 | public void onDraw(Canvas canvas) {
122 | Rect frame = CameraManager.get().getFramingRect();
123 | if (frame == null) {
124 | return;
125 | }
126 | int width = canvas.getWidth();
127 | int height = canvas.getHeight();
128 |
129 | // Draw the exterior (i.e. outside the framing rect) darkened
130 | paint.setColor(resultBitmap != null ? resultColor : maskColor);
131 | canvas.drawRect(0, 0, width, frame.top, paint);
132 | canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint);
133 | canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, paint);
134 | canvas.drawRect(0, frame.bottom + 1, width, height, paint);
135 |
136 | if (resultBitmap != null) {
137 | // Draw the opaque result bitmap over the scanning rectangle
138 | paint.setAlpha(OPAQUE);
139 | canvas.drawBitmap(resultBitmap, frame.left, frame.top, paint);
140 | } else {
141 |
142 | drawFrameBounds(canvas, frame);
143 |
144 | drawScanLight(canvas, frame);
145 |
146 | Collection currentPossible = possibleResultPoints;
147 | Collection currentLast = lastPossibleResultPoints;
148 | if (currentPossible.isEmpty()) {
149 | lastPossibleResultPoints = null;
150 | } else {
151 | possibleResultPoints = new HashSet(5);
152 | lastPossibleResultPoints = currentPossible;
153 | paint.setAlpha(OPAQUE);
154 | paint.setColor(resultPointColor);
155 |
156 | if (isCircle) {
157 | for (ResultPoint point : currentPossible) {
158 | canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 6.0f, paint);
159 | }
160 | }
161 | }
162 | if (currentLast != null) {
163 | paint.setAlpha(OPAQUE / 2);
164 | paint.setColor(resultPointColor);
165 |
166 | if (isCircle) {
167 | for (ResultPoint point : currentLast) {
168 | canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 3.0f, paint);
169 | }
170 | }
171 | }
172 |
173 | postInvalidateDelayed(ANIMATION_DELAY, frame.left, frame.top, frame.right, frame.bottom);
174 | }
175 | }
176 |
177 | // 扫描线移动的y
178 | private int scanLineTop;
179 | // 扫描线移动速度
180 | private int SCAN_VELOCITY;
181 | // 扫描线
182 | private Bitmap scanLight;
183 | // 是否展示小圆点
184 | private boolean isCircle;
185 |
186 | /**
187 | * 绘制移动扫描线
188 | *
189 | * @param canvas
190 | * @param frame
191 | */
192 | private void drawScanLight(Canvas canvas, Rect frame) {
193 |
194 | if (scanLineTop == 0) {
195 | scanLineTop = frame.top;
196 | }
197 |
198 | if (scanLineTop >= frame.bottom - 30) {
199 | scanLineTop = frame.top;
200 | } else {
201 | scanLineTop += SCAN_VELOCITY;
202 | }
203 | Rect scanRect = new Rect(frame.left, scanLineTop, frame.right,
204 | scanLineTop + 30);
205 | canvas.drawBitmap(scanLight, null, scanRect, paint);
206 | }
207 |
208 | private ValueAnimator valueAnimator;
209 |
210 |
211 |
212 |
213 | // 扫描框边角颜色
214 | private int innercornercolor;
215 | // 扫描框边角长度
216 | private int innercornerlength;
217 | // 扫描框边角宽度
218 | private int innercornerwidth;
219 |
220 | /**
221 | * 绘制取景框边框
222 | *
223 | * @param canvas
224 | * @param frame
225 | */
226 | private void drawFrameBounds(Canvas canvas, Rect frame) {
227 |
228 | /*paint.setColor(Color.WHITE);
229 | paint.setStrokeWidth(2);
230 | paint.setStyle(Paint.Style.STROKE);
231 |
232 | canvas.drawRect(frame, paint);*/
233 |
234 | paint.setColor(innercornercolor);
235 | paint.setStyle(Paint.Style.FILL);
236 |
237 | int corWidth = innercornerwidth;
238 | int corLength = innercornerlength;
239 |
240 | // 左上角
241 | canvas.drawRect(frame.left, frame.top, frame.left + corWidth, frame.top
242 | + corLength, paint);
243 | canvas.drawRect(frame.left, frame.top, frame.left
244 | + corLength, frame.top + corWidth, paint);
245 | // 右上角
246 | canvas.drawRect(frame.right - corWidth, frame.top, frame.right,
247 | frame.top + corLength, paint);
248 | canvas.drawRect(frame.right - corLength, frame.top,
249 | frame.right, frame.top + corWidth, paint);
250 | // 左下角
251 | canvas.drawRect(frame.left, frame.bottom - corLength,
252 | frame.left + corWidth, frame.bottom, paint);
253 | canvas.drawRect(frame.left, frame.bottom - corWidth, frame.left
254 | + corLength, frame.bottom, paint);
255 | // 右下角
256 | canvas.drawRect(frame.right - corWidth, frame.bottom - corLength,
257 | frame.right, frame.bottom, paint);
258 | canvas.drawRect(frame.right - corLength, frame.bottom - corWidth,
259 | frame.right, frame.bottom, paint);
260 | }
261 |
262 |
263 | public void drawViewfinder() {
264 | resultBitmap = null;
265 | invalidate();
266 | }
267 |
268 | public void addPossibleResultPoint(ResultPoint point) {
269 | possibleResultPoints.add(point);
270 | }
271 |
272 |
273 | /**
274 | * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
275 | */
276 | public static int dip2px(Context context, float dpValue) {
277 | final float scale = context.getResources().getDisplayMetrics().density;
278 | return (int) (dpValue * scale + 0.5f);
279 | }
280 |
281 |
282 | }
283 |
--------------------------------------------------------------------------------
/zxing/src/main/res/drawable/scan_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wintonBy/EasyZxing/91dc97f7c2bcb086bba93f4c6b1d2051a8a6b02c/zxing/src/main/res/drawable/scan_light.png
--------------------------------------------------------------------------------
/zxing/src/main/res/layout/act_scan.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
9 |
10 |
18 |
19 |
29 |
42 |
43 |
44 |
45 |
50 |
51 |
52 |
59 |
66 |
67 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/zxing/src/main/res/layout/camera.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/zxing/src/main/res/layout/fragment_capture.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
16 |
17 |
--------------------------------------------------------------------------------
/zxing/src/main/res/layout/layout_scan.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
24 |
25 |
--------------------------------------------------------------------------------
/zxing/src/main/res/mipmap-xhdpi/ic_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wintonBy/EasyZxing/91dc97f7c2bcb086bba93f4c6b1d2051a8a6b02c/zxing/src/main/res/mipmap-xhdpi/ic_back.png
--------------------------------------------------------------------------------
/zxing/src/main/res/mipmap-xhdpi/iv_light_switch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wintonBy/EasyZxing/91dc97f7c2bcb086bba93f4c6b1d2051a8a6b02c/zxing/src/main/res/mipmap-xhdpi/iv_light_switch.png
--------------------------------------------------------------------------------
/zxing/src/main/res/mipmap/ic_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wintonBy/EasyZxing/91dc97f7c2bcb086bba93f4c6b1d2051a8a6b02c/zxing/src/main/res/mipmap/ic_back.png
--------------------------------------------------------------------------------
/zxing/src/main/res/mipmap/iv_light_switch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wintonBy/EasyZxing/91dc97f7c2bcb086bba93f4c6b1d2051a8a6b02c/zxing/src/main/res/mipmap/iv_light_switch.png
--------------------------------------------------------------------------------
/zxing/src/main/res/raw/beep.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wintonBy/EasyZxing/91dc97f7c2bcb086bba93f4c6b1d2051a8a6b02c/zxing/src/main/res/raw/beep.ogg
--------------------------------------------------------------------------------
/zxing/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/zxing/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #59a9ff
4 |
5 | #EDEDED
6 | #ff000000
7 | #ffffffff
8 | #ffcccccc
9 | #ff404040
10 | #c0ffff00
11 | #ffffffff
12 | #ffc0c0c0
13 | #c000ff00
14 | #ffffffff
15 | #b0000000
16 | #ff808080
17 | #ffffffff
18 | #fffff0e0
19 | #ffffffff
20 | #ff000000
21 | #ff4b4b4b
22 | #ff000000
23 | #ffffffff
24 | #50000000
25 | #ffffffff
26 | #00000000
27 | #ff000000
28 | #ffff0000
29 | #60000000
30 | #58567D
31 | #686868
32 |
33 |
34 |
--------------------------------------------------------------------------------
/zxing/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/zxing/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Lib-zxing
3 |
4 |
5 | Hello blank fragment
6 |
7 |
--------------------------------------------------------------------------------
/zxing/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
12 |
13 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/zxing/src/test/java/com/zxing/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.zxing;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------