diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..be6196a10 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,21 @@ +name: Build Android + +on: [pull_request] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-java@v2 + with: + distribution: 'temurin' + java-version: '11' + - name: Build and Lint with Gradle + run: ./gradlew build + - name: Archive lint results + uses: actions/upload-artifact@v2 + with: + name: lint-results + path: "**/build/reports/lint-results*" diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 8f07e21ac..000000000 --- a/.travis.yml +++ /dev/null @@ -1,36 +0,0 @@ -language: android -jdk: oraclejdk8 -android: - components: - # Install tools twice to get the latest update - - tools - - tools - - platform-tools - - build-tools-28.0.3 - - - extra-android-support - - extra-android-m2repository - - extra-google-m2repository - licenses: - - 'android-sdk-preview-license-.+' - - 'android-sdk-license-.+' - - 'google-gdk-license-.+' - -branches: - only: - - master - -before_install: - # Android SDK installation is a mess, especially with licenses. Not sure if all of this is required, but it works. - - echo "$ANDROID_HOME" - - mkdir -p "$ANDROID_HOME/licenses" - - echo -e "\n8933bad161af4178b1185d1a37fbf41ea5269c55" > "$ANDROID_HOME/licenses/android-sdk-license" - - echo -e "\n84831b9409646a918e30573bab4c9c91346d8abd" > "$ANDROID_HOME/licenses/android-sdk-preview-license" - - yes | sdkmanager "platforms;android-27" - -script: - # build includes lint and test - - TERM=dumb ./gradlew build - -after_failure: - - cat **/build/reports/lint-results.xml diff --git a/CHANGES.md b/CHANGES.md index 7e2d4370f..9ce2ea8c9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,17 @@ +### 4.3.0 (2021-10-25) + +* Minimum SDK version 19, but requires additional config (see readme) for < 24 compatibility. +* Add ScanOptions and ScanContract for use with `registerForActivityResult()`. +* Deprecates IntentIntegrator. +* Use minimal AndroidX libraries. + +### 4.2.0 (2021-03-15) + +* Fix MediaPlayer warnings (#587). +* Prevent CameraConfigurationUtils clash (#609). +* Add licenses to POM (#556). +* Bug: Crashes on SDK versions older than 21 (#645). + ### 4.1.0 (2020-01-07) * Ability to hide the laser in ViewfinderView (#503). diff --git a/README.md b/README.md index dd2f25b54..bc35852bb 100644 --- a/README.md +++ b/README.md @@ -27,19 +27,19 @@ repositories { } dependencies { - implementation 'com.journeyapps:zxing-android-embedded:4.2.0' - implementation 'androidx.appcompat:appcompat:1.0.2' + implementation 'com.journeyapps:zxing-android-embedded:4.3.0' } - -android { - buildToolsVersion '28.0.3' // Older versions may give compile errors -} - ``` ## Older SDK versions -For Android SDK versions < 24, you can downgrade `zxing:core` to 3.3.0 or earlier for Android 14+ support: +By default, only SDK 24+ is supported, even though the library specifies 19 as the minimum version. +No guarantees are made on support for SDK versions below 24 - you'll have to test to make sure it's compatible. + +SDK versions 19 - 23 should also work, but one of the changes changes below are required, +and this is not routinely tested. + +### Option 1. Downgrade zxing:core to 3.3.0 ```groovy repositories { @@ -47,24 +47,41 @@ repositories { } dependencies { - implementation('com.journeyapps:zxing-android-embedded:4.2.0') { transitive = false } - implementation 'androidx.appcompat:appcompat:1.0.2' + implementation('com.journeyapps:zxing-android-embedded:4.3.0') { transitive = false } implementation 'com.google.zxing:core:3.3.0' } +``` +### Option 2: Desugaring (Advanced) + +This option does not require changing library versions, but may complicate the build process. + +See [Java 8+ API desugaring support](https://developer.android.com/studio/write/java8-support#library-desugaring). + +```groovy android { - buildToolsVersion '28.0.3' -} + defaultConfig { + // Important: multidex must be enabled + // https://developer.android.com/studio/build/multidex#mdex-gradle + multiDexEnabled true + minSdkVersion 19 + } -``` -You'll also need this in your Android manifest: + compileOptions { + // Flag to enable support for the new language APIs + coreLibraryDesugaringEnabled true + // Sets Java compatibility to Java 8 + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} -```xml - +dependencies { + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' + implementation "androidx.multidex:multidex:2.0.1" +} ``` -No guarantees are made on support for older SDK versions - you'll have to test to make sure it's compatible. - ## Hardware Acceleration Hardware acceleration is required since TextureView is used. @@ -75,48 +92,42 @@ Make sure it is enabled in your manifest file: ``` -## Usage with IntentIntegrator +## Usage with ScanContract -Launch the intent with the default options: -```java -new IntentIntegrator(this).initiateScan(); // `this` is the current Activity - - -// Get the results: -@Override -protected void onActivityResult(int requestCode, int resultCode, Intent data) { - IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data); - if(result != null) { - if(result.getContents() == null) { - Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show(); - } else { - Toast.makeText(this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show(); - } - } else { - super.onActivityResult(requestCode, resultCode, data); - } -} -``` +Note: `startActivityForResult` is deprecated, so this example uses `registerForActivityResult` instead. +See for details: https://developer.android.com/training/basics/intents/result -Use from a Fragment: -```java -IntentIntegrator.forFragment(this).initiateScan(); // `this` is the current Fragment +`startActivityForResult` can still be used via `IntentIntegrator`, but that is not recommended anymore. -// If you're using the support library, use IntentIntegrator.forSupportFragment(this) instead. +```java +// Register the launcher and result handler +private final ActivityResultLauncher barcodeLauncher = registerForActivityResult(new ScanContract(), + result -> { + if(result.getContents() == null) { + Toast.makeText(MyActivity.this, "Cancelled", Toast.LENGTH_LONG).show(); + } else { + Toast.makeText(MyActivity.this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show(); + } + }); + +// Launch +public void onButtonClick(View view) { + barcodeLauncher.launch(new ScanOptions()); +} ``` Customize options: ```java -IntentIntegrator integrator = new IntentIntegrator(this); -integrator.setDesiredBarcodeFormats(IntentIntegrator.ONE_D_CODE_TYPES); -integrator.setPrompt("Scan a barcode"); -integrator.setCameraId(0); // Use a specific camera of the device -integrator.setBeepEnabled(false); -integrator.setBarcodeImageEnabled(true); -integrator.initiateScan(); +ScanOptions options = new ScanOptions(); +options.setDesiredBarcodeFormats(ScanOptions.ONE_D_CODE_TYPES); +options.setPrompt("Scan a barcode"); +options.setCameraId(0); // Use a specific camera of the device +options.setBeepEnabled(false); +options.setBarcodeImageEnabled(true); +barcodeLauncher.launch(options); ``` -See [IntentIntegrator][5] for more options. +See [BarcodeOptions][5] for more options. ### Generate Barcode example @@ -152,9 +163,9 @@ Sample: ``` ```java -IntentIntegrator integrator = new IntentIntegrator(this); -integrator.setOrientationLocked(false); -integrator.initiateScan(); +ScanOptions options = new ScanOptions(); +options.setOrientationLocked(false); +barcodeLauncher.launch(options); ``` ### Customization and advanced options @@ -198,7 +209,7 @@ You can then use your local version by specifying in your `build.gradle` file: Licensed under the [Apache License 2.0][7] - Copyright (C) 2012-2018 ZXing authors, Journey Mobile + Copyright (C) 2012-201 ZXing authors, Journey Mobile Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -216,7 +227,5 @@ Licensed under the [Apache License 2.0][7] [1]: http://journeyapps.com [2]: https://github.com/zxing/zxing/ -[3]: https://github.com/zxing/zxing/wiki/Scanning-Via-Intent -[4]: https://github.com/journeyapps/zxing-android-embedded/blob/2.x/README.md -[5]: zxing-android-embedded/src/com/google/zxing/integration/android/IntentIntegrator.java +[5]: zxing-android-embedded/src/com/journeyapps/barcodescanner/ScanOptions.java [7]: http://www.apache.org/licenses/LICENSE-2.0 diff --git a/build.gradle b/build.gradle index bc84598fc..2f030a799 100644 --- a/build.gradle +++ b/build.gradle @@ -2,16 +2,10 @@ buildscript { repositories { google() mavenCentral() - jcenter { - content { - // https://youtrack.jetbrains.com/issue/IDEA-261387 - includeModule("org.jetbrains.trove4j", "trove4j") - } - } } dependencies { - classpath 'com.android.tools.build:gradle:3.5.3' + classpath 'com.android.tools.build:gradle:7.0.3' } } @@ -20,17 +14,11 @@ subprojects { google() mavenLocal() mavenCentral() - jcenter { - content { - // https://youtrack.jetbrains.com/issue/IDEA-261387 - includeModule("org.jetbrains.trove4j", "trove4j") - } - } } - version = '4.2.0' + version = '4.3.0' group = 'com.journeyapps' - ext.androidTargetSdk = 28 - ext.zxingCore = 'com.google.zxing:core:3.4.0' + ext.androidTargetSdk = 30 + ext.zxingCore = 'com.google.zxing:core:3.4.1' } diff --git a/gradle.properties b/gradle.properties index 53ae0ae47..2e145cb2e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ -android.enableJetifier=true +android.enableJetifier=false android.useAndroidX=true org.gradle.jvmargs=-Xmx1536M diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 3baa851b2..cc4fdc293 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0cbd65f2a..ffed3a254 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Sat Sep 07 15:17:02 SAST 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-all.zip diff --git a/gradlew b/gradlew index 27309d923..2fe81a7d9 100755 --- a/gradlew +++ b/gradlew @@ -1,4 +1,20 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ############################################################################## ## @@ -28,16 +44,16 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -109,8 +125,8 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` @@ -138,27 +154,30 @@ if $cygwin ; then else eval `echo args$i`="\"$arg\"" fi - i=$((i+1)) + i=`expr $i + 1` done case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=`save "$@"` -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 832fdb607..24467a141 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,90 +1,100 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/sample/build.gradle b/sample/build.gradle index 875a3aefe..329db202a 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -4,7 +4,8 @@ android { compileSdkVersion project.androidTargetSdk defaultConfig { - minSdkVersion 24 + multiDexEnabled true + minSdkVersion 19 targetSdkVersion project.androidTargetSdk versionCode 411 versionName "4.1.1" @@ -50,10 +51,19 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' } } + compileOptions { + coreLibraryDesugaringEnabled true sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + + lintOptions { + // Error: The lint detector + // androidx.appcompat.view.OnClickXmlDetector + // called context.getMainProject() during module analysis. + disable 'UsingOnClickInXml' + } } @@ -62,14 +72,18 @@ dependencies { // implementation 'com.journeyapps:zxing-android-embedded:' implementation project(':zxing-android-embedded') - implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.appcompat:appcompat:1.3.1' implementation 'androidx.legacy:legacy-support-v13:1.0.0' + implementation "androidx.activity:activity:1.3.1" + + // Desugaring and multidex is required for API < 21. + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' + implementation 'androidx.multidex:multidex:2.0.1' // leakcanary is for development purposes only // https://github.com/square/leakcanary - debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.5' - releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.5' + debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7' // AboutLibraries - implementation "com.mikepenz:aboutlibraries:6.2.3" + implementation 'com.mikepenz:aboutlibraries:6.2.3' } diff --git a/sample/src/main/java/example/zxing/MainActivity.java b/sample/src/main/java/example/zxing/MainActivity.java index 99a3b6204..dedd814ae 100644 --- a/sample/src/main/java/example/zxing/MainActivity.java +++ b/sample/src/main/java/example/zxing/MainActivity.java @@ -3,8 +3,6 @@ import android.content.Intent; import android.hardware.Camera; import android.os.Bundle; -import androidx.fragment.app.Fragment; -import androidx.appcompat.app.AppCompatActivity; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -13,14 +11,33 @@ import android.widget.Toast; import com.google.zxing.client.android.Intents; -import com.google.zxing.integration.android.IntentIntegrator; -import com.google.zxing.integration.android.IntentResult; +import com.journeyapps.barcodescanner.ScanContract; +import com.journeyapps.barcodescanner.ScanOptions; import com.mikepenz.aboutlibraries.LibsBuilder; +import androidx.activity.result.ActivityResultLauncher; +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; + public class MainActivity extends AppCompatActivity { + private final ActivityResultLauncher barcodeLauncher = registerForActivityResult(new ScanContract(), + result -> { + if(result.getContents() == null) { + Intent originalIntent = result.getOriginalIntent(); + if (originalIntent == null) { + Log.d("MainActivity", "Cancelled scan"); + Toast.makeText(MainActivity.this, "Cancelled", Toast.LENGTH_LONG).show(); + } else if(originalIntent.hasExtra(Intents.Scan.MISSING_CAMERA_PERMISSION)) { + Log.d("MainActivity", "Cancelled scan due to missing camera permission"); + Toast.makeText(MainActivity.this, "Cancelled due to missing camera permission", Toast.LENGTH_LONG).show(); + } + } else { + Log.d("MainActivity", "Scanned"); + Toast.makeText(MainActivity.this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show(); + } + }); - public final int CUSTOMIZED_REQUEST_CODE = 0x0000ffff; @Override protected void onCreate(Bundle savedInstanceState) { @@ -29,49 +46,45 @@ protected void onCreate(Bundle savedInstanceState) { } public void scanBarcode(View view) { - new IntentIntegrator(this).initiateScan(); - } - - public void scanBarcodeWithCustomizedRequestCode(View view) { - new IntentIntegrator(this).setRequestCode(CUSTOMIZED_REQUEST_CODE).initiateScan(); + barcodeLauncher.launch(new ScanOptions()); } public void scanBarcodeInverted(View view){ - IntentIntegrator integrator = new IntentIntegrator(this); - integrator.addExtra(Intents.Scan.SCAN_TYPE, Intents.Scan.INVERTED_SCAN); - integrator.initiateScan(); + ScanOptions options = new ScanOptions(); + options.addExtra(Intents.Scan.SCAN_TYPE, Intents.Scan.INVERTED_SCAN); + barcodeLauncher.launch(options); } public void scanMixedBarcodes(View view){ - IntentIntegrator integrator = new IntentIntegrator(this); - integrator.addExtra(Intents.Scan.SCAN_TYPE, Intents.Scan.MIXED_SCAN); - integrator.initiateScan(); + ScanOptions options = new ScanOptions(); + options.addExtra(Intents.Scan.SCAN_TYPE, Intents.Scan.MIXED_SCAN); + barcodeLauncher.launch(options); } public void scanBarcodeCustomLayout(View view) { - IntentIntegrator integrator = new IntentIntegrator(this); - integrator.setCaptureActivity(AnyOrientationCaptureActivity.class); - integrator.setDesiredBarcodeFormats(IntentIntegrator.ONE_D_CODE_TYPES); - integrator.setPrompt("Scan something"); - integrator.setOrientationLocked(false); - integrator.setBeepEnabled(false); - integrator.initiateScan(); + ScanOptions options = new ScanOptions(); + options.setCaptureActivity(AnyOrientationCaptureActivity.class); + options.setDesiredBarcodeFormats(ScanOptions.ONE_D_CODE_TYPES); + options.setPrompt("Scan something"); + options.setOrientationLocked(false); + options.setBeepEnabled(false); + barcodeLauncher.launch(options); } public void scanPDF417(View view) { - IntentIntegrator integrator = new IntentIntegrator(this); - integrator.setDesiredBarcodeFormats(IntentIntegrator.PDF_417); - integrator.setPrompt("Scan something"); - integrator.setOrientationLocked(false); - integrator.setBeepEnabled(false); - integrator.initiateScan(); + ScanOptions options = new ScanOptions(); + options.setDesiredBarcodeFormats(ScanOptions.PDF_417); + options.setPrompt("Scan something"); + options.setOrientationLocked(false); + options.setBeepEnabled(false); + barcodeLauncher.launch(options); } public void scanBarcodeFrontCamera(View view) { - IntentIntegrator integrator = new IntentIntegrator(this); - integrator.setCameraId(Camera.CameraInfo.CAMERA_FACING_FRONT); - integrator.initiateScan(); + ScanOptions options = new ScanOptions(); + options.setCameraId(Camera.CameraInfo.CAMERA_FACING_FRONT); + barcodeLauncher.launch(options); } public void scanContinuous(View view) { @@ -80,24 +93,26 @@ public void scanContinuous(View view) { } public void scanToolbar(View view) { - new IntentIntegrator(this).setCaptureActivity(ToolbarCaptureActivity.class).initiateScan(); + ScanOptions options = new ScanOptions().setCaptureActivity(ToolbarCaptureActivity.class); + barcodeLauncher.launch(options); } public void scanCustomScanner(View view) { - new IntentIntegrator(this).setOrientationLocked(false).setCaptureActivity(CustomScannerActivity.class).initiateScan(); + ScanOptions options = new ScanOptions().setOrientationLocked(false).setCaptureActivity(CustomScannerActivity.class); + barcodeLauncher.launch(options); } public void scanMarginScanner(View view) { - IntentIntegrator integrator = new IntentIntegrator(this); - integrator.setOrientationLocked(false); - integrator.setCaptureActivity(SmallCaptureActivity.class); - integrator.initiateScan(); + ScanOptions options = new ScanOptions(); + options.setOrientationLocked(false); + options.setCaptureActivity(SmallCaptureActivity.class); + barcodeLauncher.launch(options); } public void scanWithTimeout(View view) { - IntentIntegrator integrator = new IntentIntegrator(this); - integrator.setTimeout(8000); - integrator.initiateScan(); + ScanOptions options = new ScanOptions(); + options.setTimeout(8000); + barcodeLauncher.launch(options); } public void tabs(View view) { @@ -109,55 +124,22 @@ public void about(View view) { new LibsBuilder().start(this); } - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (requestCode != CUSTOMIZED_REQUEST_CODE && requestCode != IntentIntegrator.REQUEST_CODE) { - // This is important, otherwise the result will not be passed to the fragment - super.onActivityResult(requestCode, resultCode, data); - return; - } - switch (requestCode) { - case CUSTOMIZED_REQUEST_CODE: { - Toast.makeText(this, "REQUEST_CODE = " + requestCode, Toast.LENGTH_LONG).show(); - break; - } - default: - break; - } - - IntentResult result = IntentIntegrator.parseActivityResult(resultCode, data); - - if(result.getContents() == null) { - Intent originalIntent = result.getOriginalIntent(); - if (originalIntent == null) { - Log.d("MainActivity", "Cancelled scan"); - Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show(); - } else if(originalIntent.hasExtra(Intents.Scan.MISSING_CAMERA_PERMISSION)) { - Log.d("MainActivity", "Cancelled scan due to missing camera permission"); - Toast.makeText(this, "Cancelled due to missing camera permission", Toast.LENGTH_LONG).show(); - } - } else { - Log.d("MainActivity", "Scanned"); - Toast.makeText(this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show(); - } - } - /** * Sample of scanning from a Fragment */ public static class ScanFragment extends Fragment { - private String toast; + private final ActivityResultLauncher fragmentLauncher = registerForActivityResult(new ScanContract(), + result -> { + if(result.getContents() == null) { + Toast.makeText(getContext(), "Cancelled from fragment", Toast.LENGTH_LONG).show(); + } else { + Toast.makeText(getContext(), "Scanned from fragment: " + result.getContents(), Toast.LENGTH_LONG).show(); + } + }); public ScanFragment() { } - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - - displayToast(); - } - @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -168,29 +150,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, } public void scanFromFragment() { - IntentIntegrator.forSupportFragment(this).initiateScan(); - } - - private void displayToast() { - if(getActivity() != null && toast != null) { - Toast.makeText(getActivity(), toast, Toast.LENGTH_LONG).show(); - toast = null; - } - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data); - if(result != null) { - if(result.getContents() == null) { - toast = "Cancelled from fragment"; - } else { - toast = "Scanned from fragment: " + result.getContents(); - } - - // At this point we may or may not have a reference to the activity - displayToast(); - } + fragmentLauncher.launch(new ScanOptions()); } } } diff --git a/sample/src/main/java/example/zxing/SampleApplication.java b/sample/src/main/java/example/zxing/SampleApplication.java index bbf850d4f..2d80a0080 100644 --- a/sample/src/main/java/example/zxing/SampleApplication.java +++ b/sample/src/main/java/example/zxing/SampleApplication.java @@ -1,16 +1,13 @@ package example.zxing; -import android.app.Application; - -import com.squareup.leakcanary.LeakCanary; +import androidx.multidex.MultiDexApplication; /** * */ -public class SampleApplication extends Application { +public class SampleApplication extends MultiDexApplication { @Override public void onCreate() { super.onCreate(); - LeakCanary.install(this); } } diff --git a/sample/src/main/res/layout/activity_main.xml b/sample/src/main/res/layout/activity_main.xml index 3210cfd61..26749d4d3 100644 --- a/sample/src/main/res/layout/activity_main.xml +++ b/sample/src/main/res/layout/activity_main.xml @@ -25,12 +25,6 @@ android:text="Scan PDF417" android:onClick="scanPDF417"/> -