Compare commits

..

103 Commits

Author SHA1 Message Date
Ralf Kistner d09b7c76c3 Merge pull request #726 from yuchan2215/patch-1
Fix Typo
2022-10-21 10:40:04 +02:00
yuchan2215 3a2db7ffc6 Fix Typo 2022-10-21 12:04:14 +09:00
Ralf Kistner 2a65a6c973 Merge pull request #708 from amirrudd/patch-1
Remove duplicate in ReadMe
2022-06-16 15:14:09 +02:00
Amir Rudd 3c77f1d6c8 Remove duplicate in ReadMe 2022-06-16 15:24:55 +04:30
Ralf Kistner b6c6421dd5 Merge pull request #696 from saifkhichi96/patch-1
Added ability to customize colors in barcodes generated with BarcodeEncoder.
2022-02-21 09:58:04 +02:00
Muhammad Saif Ullah Khan 8173d4a8b2 Added color customization instructions in README 2022-02-08 18:27:41 +01:00
Muhammad Saif Ullah Khan 8fdbbbef5e Support custom colors in BarcodeEncoder.java. 2022-02-08 18:17:58 +01:00
Conrad Hofmeyr 2324a5403e Update README.md 2021-12-22 12:29:22 -07:00
Ralf Kistner c752130405 Merge pull request #673 from juliansteenbakker/make-initializeAttributes-public
imp: make initializeAttributes public
2021-11-17 10:32:59 +02:00
juliansteenbakker 1c27c8fe2d imp: make initializeAttributes public 2021-11-17 08:52:37 +01:00
Ralf Kistner aa129af542 Merge pull request #666 from journeyapps/update-readme-sdk-version
Update notes on minSdkVersion
2021-10-26 16:19:21 +02:00
Ralf Kistner 90b5db5fcd Update notes on minSdkVersion. 2021-10-26 10:49:40 +02:00
Ralf Kistner 24d02945fe Merge pull request #665 from journeyapps/fixes
v4.3.0
2021-10-25 15:54:10 +02:00
Ralf Kistner 6ccf3a9d1a Fix lint report location. 2021-10-25 15:46:32 +02:00
Ralf Kistner 23f29e5a56 Ignore lint error. 2021-10-25 15:41:21 +02:00
Ralf Kistner 1a8d949325 Tweaks. 2021-10-25 15:37:09 +02:00
Ralf Kistner f1554b7478 Use GitHub Actions. 2021-10-25 15:32:46 +02:00
Ralf Kistner cc12c103e0 v4.3.0 and cleanup. 2021-10-25 15:22:01 +02:00
Ralf Kistner a13ce2b161 Cleanup. 2021-10-25 15:06:58 +02:00
Ralf Kistner 0c97cf70cc ScanOptions and ScanContract. 2021-10-25 14:57:43 +02:00
Ralf Kistner 9beeac7960 minSdkVersion 19. Multidex and desugaring. 2021-10-25 13:53:35 +02:00
Ralf Kistner cc34502f13 Smaller libs. 2021-10-25 13:53:25 +02:00
Ralf Kistner 2221621de9 Some cleanup. 2021-10-25 13:03:59 +02:00
Ralf Kistner 4d4c5a2c4e Disable jetifier. 2021-10-25 13:03:51 +02:00
Ralf Kistner 65d2716c71 Upgrade tooling. 2021-10-25 13:01:17 +02:00
Ralf Kistner 7fd1ab8794 Fix lint issues. 2021-10-25 13:00:40 +02:00
Ralf Kistner 630e3cc0f8 Fix API 19 crash. 2021-10-25 13:00:19 +02:00
Ralf Kistner 40260272fc Merge pull request #617 from journeyapps/maven-central
Maven Central
2021-03-15 17:45:32 +02:00
Ralf Kistner f54615e43a Update metadata and scripts for Maven Central. 2021-03-15 11:18:34 +02:00
Ralf Kistner 1acc3a6f4f Merge pull request #605 from devzeze/devzeze-fix556
fix #556 add licenses to POM
2021-02-12 10:32:22 +02:00
Ralf Kistner 73093b9b4f Merge pull request #587 from ANewGalaxy/master
Fixing MediaPlayer warnings;
2021-02-12 10:30:32 +02:00
Ralf Kistner db85816b3d Merge pull request #609 from nodh/feature/preventclassclash
Move CameraConfigurationUtils to prevent clash with other ZXing libraries
2021-02-12 10:29:37 +02:00
Christian Kollmann 6a3d857019 Move CameraConfigurationUtils to prevent clash with com.google.zxing:android-core 2021-02-12 07:26:12 +01:00
devzeze 6c8ea7e3fd fix #556 2021-02-03 16:07:17 +01:00
ANewGalaxy 35ee545f8b Replaced setAudioStreamType method call with setAudioAttributes call to fix warnings about stream types. Also removed unused import. 2020-12-11 22:00:01 -05:00
ANewGalaxy 5d9e2c3756 Added reset calls before each release call 2020-12-11 21:57:36 -05:00
ANewGalaxy cce2a300ef Fixing MediaPlayer warnings; 2020-12-11 21:48:29 -05:00
Ralf Kistner 13440ad875 Update readme. 2020-02-11 09:55:51 +02:00
Ralf Kistner 5a2470f034 Merge branch 'master' of github.com:journeyapps/zxing-android-embedded 2020-02-11 09:52:51 +02:00
Ralf Kistner 545672bb8f Update README.md
Fix the version.
2020-01-31 17:24:51 +02:00
Ralf Kistner 542dc66090 Merge pull request #530 from lukassos/master
correct release version 4.0.2
2020-01-17 14:44:06 +02:00
Lukassos ea414a236e correct release version 4.0.2
After two days of headaches, looked into CHANGES.md where 4.0.0 is marked as broken - we should use 4.0.2
2020-01-17 12:14:32 +01:00
Ralf Kistner 1ba1ded540 Merge pull request #529 from hannesa2/ReduceTravisBuilds
Reduce Travis builds
2020-01-08 17:05:52 +02:00
Ralf Kistner 4893bcc194 Merge pull request #528 from hannesa2/AndroidStudio-3.5.3
Android Studio 3.5.3
2020-01-08 10:13:54 +02:00
Hannes Achleitner 6498fad6a7 Reduce Travis builds 2020-01-07 19:52:44 +01:00
Hannes Achleitner f7f779d7ac Android Studio 3.5.3 2020-01-07 19:49:36 +01:00
Ralf Kistner c555ffbe05 Release 4.1.0 2020-01-07 14:24:05 +02:00
Andre Ippisch e0d340952d Camera permission behaviour (#505)
* Remove unused else

* Remove SDK version check since we are on minimum 24 already

* Add intent key about missing camera permission

* Add boolean value to show error dialog

- always true for the beginning to keep current behaviour

* Make displaying an error dialog for missing camera permissions optional

* Add intent extras for Intent initialisation

* Initialise camera permission dialog visibility from Intent

* Add original intent to IntentResult

* Use original intent in IntentResult

* Make onRequestPermissionResult public again

* Forward onRequestPermissionResult

* React on Intent information

- for example on the missing camera permission

* Revert "Remove SDK version check since we are on minimum 24 already"

This reverts commit 8f79f56a

* Add missing imports
2020-01-07 14:00:51 +02:00
Ralf Kistner 9b924e6875 Merge pull request #511 from hannesa2/AndroidStudio-3.5.2
Android Studio 3.5.2
2020-01-07 13:55:48 +02:00
Ralf Kistner 8df0cb554a Merge pull request #527 from yands11/master
Apply space convention after 'if'
2020-01-07 13:54:55 +02:00
Ralf Kistner 09d992ddfa Merge pull request #519 from bekabot/master
Remove unneeded type casts & fix comment typo in DecoratedBarcodeView.java
2020-01-07 13:54:27 +02:00
Ralf Kistner 95cd4a3a4d Merge pull request #512 from hannesa2/SomeCodeCleanup
some code cleanup
2020-01-07 13:54:02 +02:00
youngseok 7e5bbd2997 Apply space convention after 'if' 2020-01-07 14:37:28 +09:00
bekabot 8d8cd7d445 remove unneeded type casts 2019-12-10 13:40:43 +06:00
bekabot bd857c68eb fix comment 2019-12-10 13:35:13 +06:00
Hannes Achleitner 0fdfbce9fb some code cleanup 2019-11-17 13:49:59 +01:00
Hannes Achleitner eba457ee9e Android Studio 3.5.2 2019-11-17 13:42:27 +01:00
Ralf Kistner 9319110de8 Merge pull request #504 from anipp100/default-method
Use default annotation for optional interface method
2019-10-24 09:33:31 +02:00
Ralf Kistner ee4b181f23 Merge pull request #506 from anipp100/lambda-runnable
Use lambda for standalone Runnables
2019-10-24 09:33:12 +02:00
Ralf Kistner a4f751500c Fix instructions for min-sdk 14.
Fixes #507.
2019-10-22 10:05:01 +02:00
Andre Ippisch 75b4aa57f5 Use lambda for standalone Runnables 2019-10-18 14:39:58 +02:00
Andre Ippisch eb4cbd5095 Use default annotation for optional interface method 2019-10-18 12:48:47 +02:00
Andre Ippisch aa4fca5dae Let visibility of "laser scanner" be set (#503)
* Add laser visibility attribute

* Add laser visibility attribute usage to sample project

- set to true to stick with the current behavior
- included for didactic reasons

* Add laser visibility attribute to ViewfinderView and set it accordingly

* Draw "laser scanner" only if wanted

* Let laser visibility be changed programmatically

* Add sample code to show how laser visibility can be changed programmatically
2019-10-17 14:21:23 +02:00
Ralf Kistner d22b581cd3 Merge pull request #495 from journeyapps/release-401
Release v4.0.2
2019-09-07 19:04:30 +02:00
Ralf Kistner 9349b31ab3 v4.0.2. 2019-09-07 19:01:10 +02:00
Ralf Kistner c0c8363f85 More publishing fixes. 2019-09-07 19:00:32 +02:00
Ralf Kistner 27c22e8ffe v4.0.1 2019-09-07 18:53:01 +02:00
Ralf Kistner d77fa29226 Fix bintray publishing issues. 2019-09-07 18:51:44 +02:00
Ralf Kistner 9aa5381c2b Merge pull request #494 from journeyapps/upgrade-zxing
v4.0.0
2019-09-07 18:17:40 +02:00
Ralf Kistner 3a7612661a v4.0.0.; update docs. 2019-09-07 18:03:30 +02:00
Ralf Kistner 70f4bbb8de Merge pull request #493 from journeyapps/preview-sizing
Fix preview sizing & fix ResultPoints for front camera
2019-09-07 17:57:56 +02:00
Ralf Kistner 363ad77540 Upgrade zxing; min sdk of 24. 2019-09-07 17:52:00 +02:00
Ralf Kistner 62547c10d7 Internal support for downscaling before decoding.
Fix ResultPoint transformation for mirrored camera.
2019-09-07 17:43:08 +02:00
Ralf Kistner 0de49aa7c8 Check scaled preview size even earlier. 2019-09-07 15:49:52 +02:00
Ralf Kistner 1a1c8d0e66 Merge pull request #463 from lterminiello/fixArithmeticException
fix ArithmeticException in CameraPreview
2019-09-07 15:45:25 +02:00
Ralf Kistner 31332404fc Merge pull request #492 from journeyapps/upgrade
Upgrade tooling
2019-09-07 15:35:48 +02:00
Ralf Kistner 28c646b9e2 Merge pull request #469 from adrianoluis/more-extras-array
Adds support to send Arrays as more extras.
2019-09-07 15:35:33 +02:00
Ralf Kistner c0c0fcd745 More tooling upgrades. 2019-09-07 15:28:29 +02:00
Ralf Kistner 98d00abcbd Remove sample-nosupport. 2019-09-07 15:28:18 +02:00
Ralf Kistner 7042d74f4a Merge pull request #438 from journeyapps/androidx
Switch to androidx
2019-09-07 15:12:11 +02:00
Adriano Rocha 94ae63d857 Adds support to send Arrays as more extras. 2019-04-01 22:18:04 -07:00
Lucas Marcelo Terminiello 0e7413e1f7 fix ArithmeticException in CameraPreview 2019-02-27 14:37:57 -03:00
Ralf Kistner 82e8f9afcc Switch to androidx. 2018-11-02 20:21:21 +02:00
Ralf Kistner 6556f81558 Merge branch 'akallabeth-about_library_support' 2018-11-02 20:17:58 +02:00
Ralf Kistner 5983e2fb8e Add AboutLibaries to the sample app. 2018-11-02 20:16:13 +02:00
Ralf Kistner be04a7587f Merge branch 'about_library_support' of https://github.com/akallabeth/zxing-android-embedded into akallabeth-about_library_support 2018-11-02 19:49:31 +02:00
Ralf Kistner 330cb2b63b Merge branch 'master' of github.com:journeyapps/zxing-android-embedded 2018-11-02 19:47:32 +02:00
Ralf Kistner 6b49e8774f Merge branch 'amadeu01-change-mask-color-programmatically' 2018-11-02 19:46:50 +02:00
Ralf Kistner 209e1c9a04 Remove redundant call; set random color on every launch in sample. 2018-11-02 19:46:24 +02:00
Ralf Kistner c7a143499e Merge branch 'change-mask-color-programmatically' of https://github.com/amadeu01/zxing-android-embedded into amadeu01-change-mask-color-programmatically 2018-11-02 19:42:19 +02:00
Ralf Kistner a4dfc2fca4 Merge pull request #406 from reusch/feature/torch-at-startup
Torch at camera startup
2018-11-02 19:39:56 +02:00
Ralf Kistner 98b69af339 Merge pull request #412 from greatjack1/master
changed compile to implementation in README.md
2018-11-02 19:39:03 +02:00
Ralf Kistner 40010a62df Merge pull request #383 from CaramelHeaven/feature/update_sample
Updated sample
2018-11-02 19:38:39 +02:00
Ralf Kistner 5927f38a1d Merge branch 'MicroSpecWes-master' 2018-11-02 19:37:24 +02:00
Ralf Kistner f2a477b647 More updates and fixes. 2018-11-02 19:37:12 +02:00
Amadeu Cavalcante 65aaa93a27 Added support for programmatically change ViewfinderView mask color 2018-10-15 21:24:58 -03:00
Armin Novak 1e1b075f13 Added resource strings for AboutLibraries 2018-08-13 13:57:06 +02:00
greatjack1 224bfd6ea2 changed compile to implementation in README.md 2018-07-16 14:58:28 -04:00
Thomas Reusch c1a3786c17 torch at camera startup
add option to enable the torch at camera startup when using IntentIntegrator
2018-06-17 21:56:24 +02:00
Wesley Crick 2af07f95cf Gradle Update and SDK 27
Updated android support dependencies to 27.1.1.

Update deprecated "compile" to "implementation".
2018-05-30 16:35:42 -04:00
CaramelHeaven 4e7ee70b73 Updated sample 2018-03-30 23:11:59 +04:00
Ralf Kistner aec45c4f10 Add note on hardware acceleration.
Fixes #373.
2018-03-06 15:05:41 +02:00
Ralf Kistner c1918b32fb Fix and clarify Android SDK version notes. 2018-03-05 19:15:42 +02:00
75 changed files with 1616 additions and 991 deletions
+21
View File
@@ -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*"
+3
View File
@@ -8,3 +8,6 @@ maven-repository
local.properties
mvn-clone
*.keystore
.project
.settings
.classpath
-31
View File
@@ -1,31 +0,0 @@
language: android
jdk: oraclejdk8
android:
components:
# Install tools twice to get the latest update
- tools
- tools
- platform-tools
- build-tools-27.0.3
- extra-android-support
- extra-android-m2repository
- extra-google-m2repository
licenses:
- 'android-sdk-preview-license-.+'
- 'android-sdk-license-.+'
- 'google-gdk-license-.+'
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
+34 -2
View File
@@ -1,7 +1,39 @@
### 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).
* Make possibleResultPoints method in BarcodeCallback optional (#504).
* Ability to customize or disable the permission error dialog (#505).
### 4.0.2 (2019-09-07)
* Use androidx.
* Use zxing:core 3.4.0 by default.
* Minimum SDK version 24.
* Fix ArithmeticException.
* Fix ResultPoint locations when camera is mirrored.
### 4.0.0 / 4.0.1 (2019-09-07)
* Broken release - use 4.0.2.
### 3.6.0 (2018-03-04)
* Minimum SDK version 14.
* Use zxing:core 3.3.2 by default (#360).
* Minimum SDK version 19, or 14 by using zxing:core 3.3.0.
* Fix preview race condition (#324).
* Request code can now specified per Intent, instead of globally (#287).
* More helpers to specify barcode formats.
@@ -26,7 +58,7 @@ Changes:
* Beep on scan is now controlled only by the media volume, and still plays
even if the device is in "silent mode", as long as the media volume is not muted.
* The 150ms delay after scanning is removed.
Fixes:
* An issue where the beep sometimes played twice is fixed (#221).
+124 -58
View File
@@ -13,90 +13,150 @@ Features:
A sample application is available in [Releases](https://github.com/journeyapps/zxing-android-embedded/releases).
By default, Android SDK 24+ is required because of `zxing:core` 3.4.x.
SDK 19+ is supported with additional configuration, see [Older SDK versions](#older-sdk-versions).
## Adding aar dependency with Gradle
From version 3.6.0, only Android SDK 19+ is supported.this is a single library, supporting Gingerbread and later versions of Android
(API level 9+). If you need support for earlier Android versions, use [version 2][4].
Add the following to your build.gradle file:
Add the following to your `build.gradle` file:
```groovy
// Config for SDK 24+
repositories {
jcenter()
mavenCentral()
}
dependencies {
compile 'com.journeyapps:zxing-android-embedded:3.6.0'
compile 'com.android.support:appcompat-v7:25.3.1' // Version 23+ is required
implementation 'com.journeyapps:zxing-android-embedded:4.3.0'
}
android {
buildToolsVersion '27.0.3' // Older versions may give compile errors
}
```
Android 14+ support can still be achieved by downgrading zxing:core:
## Older SDK versions
By default, only SDK 24+ will work, even though the library specifies 19 as the minimum version.
For SDK versions 19+, one of the changes below are required.
Some older SDK versions below 19 may work, but this is not tested or supported.
### Option 1. Downgrade zxing:core to 3.3.0
```groovy
repositories {
jcenter()
mavenCentral()
}
dependencies {
compile('com.journeyapps:zxing-android-embedded:3.6.0') { transitive = false }
compile 'com.android.support:appcompat-v7:25.3.1' // Version 23+ is required
compile 'com.google.zxing:core:3.3.0'
implementation('com.journeyapps:zxing-android-embedded:4.3.0') { transitive = false }
implementation 'com.google.zxing:core:3.3.0'
}
android {
buildToolsVersion '27.0.3' // Older versions may give compile errors
}
```
## Usage with IntentIntegrator
### Option 2: Desugaring (Advanced)
Launch the intent with the default options:
```java
new IntentIntegrator(this).initiateScan(); // `this` is the current Activity
This option does not require changing library versions, but may complicate the build process.
This requires Android Gradle Plugin version 4.0.0 or later.
// 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);
See [Java 8+ API desugaring support](https://developer.android.com/studio/write/java8-support#library-desugaring).
Example for SDK 21+:
```groovy
android {
defaultConfig {
minSdkVersion 21
}
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
}
}
dependencies {
implementation 'com.journeyapps:zxing-android-embedded:4.3.0'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
}
```
Use from a Fragment:
```java
IntentIntegrator.forFragment(this).initiateScan(); // `this` is the current Fragment
SDK 19+ additionally requires multiDex. In addition to these gradle config changes, the Application
class must also be changed. See for details: [Configure your app for multidex](https://developer.android.com/studio/build/multidex#mdex-gradle).
// If you're using the support library, use IntentIntegrator.forSupportFragment(this) instead.
```groovy
android {
defaultConfig {
multiDexEnabled true
minSdkVersion 19
}
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
}
}
dependencies {
implementation 'com.journeyapps:zxing-android-embedded:4.3.0'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
implementation "androidx.multidex:multidex:2.0.1"
}
```
## Hardware Acceleration
Hardware acceleration is required since TextureView is used.
Make sure it is enabled in your manifest file:
```xml
<application android:hardwareAccelerated="true" ... >
```
## Usage with ScanContract
Note: `startActivityForResult` is deprecated, so this example uses `registerForActivityResult` instead.
See for details: https://developer.android.com/training/basics/intents/result
`startActivityForResult` can still be used via `IntentIntegrator`, but that is not recommended anymore.
```java
// Register the launcher and result handler
private final ActivityResultLauncher<ScanOptions> 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
@@ -114,6 +174,12 @@ try {
}
```
To customize the generated barcode image, use the `setBackgroundColor` and `setForegroundColor` functions of the
`BarcodeEncoder` class with a [`@ColorInt`](https://developer.android.com/reference/androidx/annotation/ColorInt)
value to update the background and foreground colors of the barcode respectively. By default, the barcode has a
white background and black foreground.
### Changing the orientation
To change the orientation, specify the orientation in your `AndroidManifest.xml` and let the `ManifestMerger` to update the Activity's definition.
@@ -128,9 +194,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
@@ -140,6 +206,8 @@ See [EMBEDDING](EMBEDDING.md).
For more advanced options, look at the [Sample Application](https://github.com/journeyapps/zxing-android-embedded/blob/master/sample/src/main/java/example/zxing/MainActivity.java),
and browse the source code of the library.
This is considered advanced usage, and is not well-documented or supported.
## Android Permissions
The camera permission is required for barcode scanning to function. It is automatically included as
@@ -165,14 +233,14 @@ You can then use your local version by specifying in your `build.gradle` file:
## Sponsored by
[JourneyApps][1] - Creating business solutions with mobile apps. Fast.
[JourneyApps][1]
## License
Licensed under the [Apache License 2.0][7]
Copyright (C) 2012-2018 ZXing authors, Journey Mobile
Copyright (C) 2012-2022 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.
@@ -190,7 +258,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
+7 -12
View File
@@ -1,29 +1,24 @@
buildscript {
repositories {
jcenter()
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
classpath 'com.android.tools.build:gradle:7.0.3'
}
}
subprojects {
repositories {
jcenter()
google()
mavenLocal()
mavenCentral()
}
version = '3.6.0'
version = '4.3.0'
group = 'com.journeyapps'
ext.androidBuildTools = '27.0.3'
ext.androidTargetSdk = 27
ext.zxingCore = 'com.google.zxing:core:3.3.2'
ext.androidTargetSdk = 30
ext.zxingCore = 'com.google.zxing:core:3.4.1'
}
repositories {
google()
}
+2
View File
@@ -1 +1,3 @@
android.enableJetifier=false
android.useAndroidX=true
org.gradle.jvmargs=-Xmx1536M
Binary file not shown.
+1 -2
View File
@@ -1,6 +1,5 @@
#Sun Mar 04 11:52:45 SAST 2018
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-4.1-all.zip
Vendored
+42 -23
View File
@@ -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" "$@"
Vendored
+100 -90
View File
@@ -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
-1
View File
@@ -1 +0,0 @@
/build
-24
View File
@@ -1,24 +0,0 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion project.androidTargetSdk
buildToolsVersion project.androidBuildTools
defaultConfig {
minSdkVersion 14
targetSdkVersion project.androidTargetSdk
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
dependencies {
compile(project(':zxing-android-embedded')) { transitive = true }
}
-17
View File
@@ -1,17 +0,0 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /home/ralf/apps/android-studio/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="example.zxing" >
<application
android:allowBackup="true"
android:icon="@drawable/icon"
android:label="@string/app_name" >
<activity
android:name="example.zxing.MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
@@ -1,106 +0,0 @@
package example.zxing;
import android.app.Activity;
import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void scanBarcode(View view) {
new IntentIntegrator((Activity)this).initiateScan();
}
public void scanBarcodeCustomOptions(View view) {
IntentIntegrator integrator = new IntentIntegrator(this);
integrator.setDesiredBarcodeFormats(IntentIntegrator.ONE_D_CODE_TYPES);
integrator.initiateScan();
}
@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 {
// This is important, otherwise the result will not be passed to the fragment
super.onActivityResult(requestCode, resultCode, data);
}
}
/**
* Sample of scanning from a Fragment
*/
public static class ScanFragment extends Fragment {
private String toast;
public ScanFragment() {
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
displayToast();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_scan, container, false);
Button scan = (Button) view.findViewById(R.id.scan_from_fragment);
scan.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
scanFromFragment();
}
});
return view;
}
public void scanFromFragment() {
IntentIntegrator.forFragment(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();
}
}
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

@@ -1,33 +0,0 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="example.zxing.MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/scan_barcode"
android:onClick="scanBarcode"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/custom_options"
android:onClick="scanBarcodeCustomOptions"/>
<fragment
android:tag="scan_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="example.zxing.MainActivity$ScanFragment" tools:layout="@layout/fragment_scan" />
</LinearLayout>
@@ -1,16 +0,0 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:context="example.zxing.MainActivity"
tools:showIn="@layout/activity_main">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/scan_from_fragment"
android:id="@+id/scan_from_fragment"/>
</LinearLayout>
@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>
@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources tools:ignore="MissingTranslation" xmlns:tools="http://schemas.android.com/tools">
<string name="app_name">ZXing Sample</string>
<string name="scan_barcode">Scan Barcode</string>
<string name="custom_options">Custom Options</string>
<string name="scan_from_fragment">Scan from fragment</string>
</resources>
@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="android:Theme">
</style>
</resources>
-1
View File
@@ -1 +0,0 @@
/build
+33 -12
View File
@@ -2,13 +2,13 @@ apply plugin: 'com.android.application'
android {
compileSdkVersion project.androidTargetSdk
buildToolsVersion project.androidBuildTools
defaultConfig {
minSdkVersion 14
multiDexEnabled true
minSdkVersion 19
targetSdkVersion project.androidTargetSdk
versionCode 360
versionName "3.6.0"
versionCode 411
versionName "4.1.1"
}
def validConfig
@@ -22,9 +22,9 @@ android {
keystoreFile = properties.getProperty('keystore.file')
keystorePassword = properties.getProperty('keystore.password')
keystoreAlias = properties.getProperty('keystore.alias')
validConfig = keystoreFile != null && keystorePassword != null && keystoreAlias != null;
validConfig = keystoreFile != null && keystorePassword != null && keystoreAlias != null
} catch (error) {
validConfig = false;
validConfig = false
}
if (validConfig) {
@@ -51,18 +51,39 @@ 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'
}
}
dependencies {
// If you use this from an external project, use the following instead:
// compile 'com.journeyapps:zxing-android-embedded:<version>'
compile project(':zxing-android-embedded')
// implementation 'com.journeyapps:zxing-android-embedded:<version>'
implementation project(':zxing-android-embedded')
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
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support:support-v13:25.3.1'
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5'
releaseCompile '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'
}
@@ -17,7 +17,6 @@ import com.journeyapps.barcodescanner.DefaultDecoderFactory;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
@@ -25,7 +24,6 @@ import java.util.List;
* a barcode is scanned.
*/
public class ContinuousCaptureActivity extends Activity {
private static final String TAG = ContinuousCaptureActivity.class.getSimpleName();
private DecoratedBarcodeView barcodeView;
private BeepManager beepManager;
private String lastText;
@@ -44,7 +42,7 @@ public class ContinuousCaptureActivity extends Activity {
beepManager.playBeepSoundAndVibrate();
//Added preview of scanned barcode
ImageView imageView = (ImageView) findViewById(R.id.barcodePreview);
ImageView imageView = findViewById(R.id.barcodePreview);
imageView.setImageBitmap(result.getBitmapWithResultPoints(Color.YELLOW));
}
@@ -59,9 +57,10 @@ public class ContinuousCaptureActivity extends Activity {
setContentView(R.layout.continuous_scan);
barcodeView = (DecoratedBarcodeView) findViewById(R.id.barcode_scanner);
barcodeView = findViewById(R.id.barcode_scanner);
Collection<BarcodeFormat> formats = Arrays.asList(BarcodeFormat.QR_CODE, BarcodeFormat.CODE_39);
barcodeView.getBarcodeView().setDecoderFactory(new DefaultDecoderFactory(formats));
barcodeView.initializeFromIntent(getIntent());
barcodeView.decodeContinuous(callback);
beepManager = new BeepManager(this);
@@ -2,13 +2,19 @@ package example.zxing;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import androidx.annotation.NonNull;
import com.journeyapps.barcodescanner.CaptureManager;
import com.journeyapps.barcodescanner.DecoratedBarcodeView;
import com.journeyapps.barcodescanner.ViewfinderView;
import java.util.Random;
/**
* Custom Scannner Activity extending from Activity to display a custom layout form scanner view.
@@ -19,16 +25,19 @@ public class CustomScannerActivity extends Activity implements
private CaptureManager capture;
private DecoratedBarcodeView barcodeScannerView;
private Button switchFlashlightButton;
private ViewfinderView viewfinderView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_scanner);
barcodeScannerView = (DecoratedBarcodeView)findViewById(R.id.zxing_barcode_scanner);
barcodeScannerView = findViewById(R.id.zxing_barcode_scanner);
barcodeScannerView.setTorchListener(this);
switchFlashlightButton = (Button)findViewById(R.id.switch_flashlight);
switchFlashlightButton = findViewById(R.id.switch_flashlight);
viewfinderView = findViewById(R.id.zxing_viewfinder_view);
// if the device does not have flashlight in its camera,
// then remove the switch flashlight button...
@@ -38,7 +47,11 @@ public class CustomScannerActivity extends Activity implements
capture = new CaptureManager(this, barcodeScannerView);
capture.initializeFromIntent(getIntent(), savedInstanceState);
capture.setShowMissingCameraPermissionDialog(false);
capture.decode();
changeMaskColor(null);
changeLaserVisibility(true);
}
@Override
@@ -87,6 +100,16 @@ public class CustomScannerActivity extends Activity implements
}
}
public void changeMaskColor(View view) {
Random rnd = new Random();
int color = Color.argb(100, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
viewfinderView.setMaskColor(color);
}
public void changeLaserVisibility(boolean visible) {
viewfinderView.setLaserVisibility(visible);
}
@Override
public void onTorchOn() {
switchFlashlightButton.setText(R.string.turn_off_flashlight);
@@ -96,4 +119,9 @@ public class CustomScannerActivity extends Activity implements
public void onTorchOff() {
switchFlashlightButton.setText(R.string.turn_on_flashlight);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
capture.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
@@ -3,9 +3,6 @@ package example.zxing;
import android.content.Intent;
import android.hardware.Camera;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -14,14 +11,33 @@ import android.widget.Button;
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.CameraPreview;
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<ScanOptions> 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) {
@@ -30,49 +46,45 @@ public class MainActivity extends AppCompatActivity {
}
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) {
@@ -81,24 +93,26 @@ public class MainActivity extends AppCompatActivity {
}
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) {
@@ -106,87 +120,37 @@ public class MainActivity extends AppCompatActivity {
startActivity(intent);
}
@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) {
Log.d("MainActivity", "Cancelled scan");
Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show();
} else {
Log.d("MainActivity", "Scanned");
Toast.makeText(this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show();
}
public void about(View view) {
new LibsBuilder().start(this);
}
/**
* Sample of scanning from a Fragment
*/
public static class ScanFragment extends Fragment {
private String toast;
private final ActivityResultLauncher<ScanOptions> 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) {
View view = inflater.inflate(R.layout.fragment_scan, container, false);
Button scan = (Button) view.findViewById(R.id.scan_from_fragment);
scan.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
scanFromFragment();
}
});
Button scan = view.findViewById(R.id.scan_from_fragment);
scan.setOnClickListener(v -> scanFromFragment());
return view;
}
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());
}
}
}
@@ -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);
}
}
@@ -2,13 +2,15 @@ package example.zxing;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.fragment.app.FragmentTransaction;
import androidx.legacy.app.FragmentStatePagerAdapter;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -17,15 +19,14 @@ import com.journeyapps.barcodescanner.CameraPreview;
import com.journeyapps.barcodescanner.DecoratedBarcodeView;
public class TabbedScanning extends AppCompatActivity implements ActionBar.TabListener {
private static final String TAG = TabbedScanning.class.getSimpleName();
/**
* The {@link android.support.v4.view.PagerAdapter} that will provide
* The {@link PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {@link FragmentPagerAdapter} derivative, which will keep every
* loaded fragment in memory. If this becomes too memory intensive, it
* may be best to switch to a
* {@link android.support.v13.app.FragmentStatePagerAdapter}.
* {@link FragmentStatePagerAdapter}.
*/
private SectionsPagerAdapter mSectionsPagerAdapter;
@@ -44,7 +45,7 @@ public class TabbedScanning extends AppCompatActivity implements ActionBar.TabLi
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager = findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
// Set up the action bar.
@@ -112,7 +113,7 @@ public class TabbedScanning extends AppCompatActivity implements ActionBar.TabLi
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_tabbed_scanning, container, false);
barcodeView = (DecoratedBarcodeView)rootView.findViewById(R.id.barcode_view);
barcodeView = rootView.findViewById(R.id.barcode_view);
return rootView;
}
@@ -165,7 +166,7 @@ public class TabbedScanning extends AppCompatActivity implements ActionBar.TabLi
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_tabbed_camera, container, false);
cameraPreview = (CameraPreview)rootView.findViewById(R.id.camera_preview);
cameraPreview = rootView.findViewById(R.id.camera_preview);
return rootView;
}
@@ -200,14 +201,14 @@ public class TabbedScanning extends AppCompatActivity implements ActionBar.TabLi
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends android.support.v4.app.FragmentPagerAdapter {
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public android.support.v4.app.Fragment getItem(int position) {
public Fragment getItem(int position) {
if(position == 0) {
return ScanFragment.newInstance();
} else {
@@ -1,9 +1,8 @@
package example.zxing;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.view.KeyEvent;
import com.journeyapps.barcodescanner.CaptureManager;
@@ -21,12 +20,12 @@ public class ToolbarCaptureActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.capture_appcompat);
Toolbar toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar);
Toolbar toolbar = findViewById(R.id.my_awesome_toolbar);
toolbar.setTitle("Scan Barcode");
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
barcodeScannerView = (DecoratedBarcodeView)findViewById(R.id.zxing_barcode_scanner);
barcodeScannerView = findViewById(R.id.zxing_barcode_scanner);
capture = new CaptureManager(this, barcodeScannerView);
capture.initializeFromIntent(getIntent(), savedInstanceState);
+8 -6
View File
@@ -25,12 +25,6 @@
android:text="Scan PDF417"
android:onClick="scanPDF417"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/scan_barcode_with_request_code"
android:onClick="scanBarcodeWithCustomizedRequestCode"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -98,6 +92,14 @@
android:layout_height="wrap_content"
android:text="@string/tabs"
android:onClick="tabs"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/about"
android:onClick="about"/>
</LinearLayout>
@@ -1,4 +1,4 @@
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.viewpager.widget.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
@@ -22,7 +22,7 @@
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
<androidx.appcompat.widget.Toolbar
android:id="@+id/my_awesome_toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
@@ -17,6 +17,7 @@
app:zxing_possible_result_points="@color/zxing_custom_possible_result_points"
app:zxing_result_view="@color/zxing_custom_result_view"
app:zxing_viewfinder_laser="@color/zxing_custom_viewfinder_laser"
app:zxing_viewfinder_laser_visibility="true"
app:zxing_viewfinder_mask="@color/zxing_custom_viewfinder_mask"/>
<TextView
+1
View File
@@ -16,5 +16,6 @@
<string name="turn_off_flashlight">Turn off Flashlight</string>
<string name="title_activity_tabbed_scanning">Tabbed Scanning</string>
<string name="tabs">Tabs</string>
<string name="about">About</string>
</resources>
-1
View File
@@ -1,3 +1,2 @@
include ':zxing-android-embedded'
include ':sample'
include ':sample-nosupport'
@@ -18,8 +18,6 @@
<uses-permission android:name="android.permission.CAMERA"/>
<uses-sdk android:minSdkVersion="14" />
<!-- Don't require camera, as this requires a rear camera. This allows it to work on the Nexus 7 -->
<uses-feature android:name="android.hardware.camera" android:required="false"/>
<uses-feature android:name="android.hardware.camera.front" android:required="false"/>
+96 -33
View File
@@ -1,23 +1,48 @@
apply plugin: 'com.android.library'
apply plugin: 'maven-publish'
apply plugin: 'com.jfrog.bintray'
apply plugin: 'signing'
ext.artifactId = 'zxing-android-embedded'
// Publishing config from https://getstream.io/blog/publishing-libraries-to-mavencentral-2021/
ext["signing.keyId"] = ''
ext["signing.password"] = ''
ext["signing.secretKeyRingFile"] = ''
ext["ossrhUsername"] = ''
ext["ossrhPassword"] = ''
ext["sonatypeStagingProfileId"] = ''
File secretPropsFile = project.rootProject.file('local.properties')
if (secretPropsFile.exists()) {
Properties p = new Properties()
p.load(new FileInputStream(secretPropsFile))
p.each { name, value ->
ext[name] = value
}
} else {
ext["signing.keyId"] = System.getenv('SIGNING_KEY_ID')
ext["signing.password"] = System.getenv('SIGNING_PASSWORD')
ext["signing.secretKeyRingFile"] = System.getenv('SIGNING_SECRET_KEY_RING_FILE')
ext["ossrhUsername"] = System.getenv('OSSRH_USERNAME')
ext["ossrhPassword"] = System.getenv('OSSRH_PASSWORD')
ext["sonatypeStagingProfileId"] = System.getenv('SONATYPE_STAGING_PROFILE_ID')
}
dependencies {
compile project.zxingCore
api project.zxingCore
compile 'com.android.support:support-v4:25.3.1'
implementation 'androidx.core:core:1.6.0'
implementation 'androidx.fragment:fragment:1.3.6'
testCompile 'junit:junit:4.12'
testCompile "org.mockito:mockito-core:1.9.5"
testImplementation 'junit:junit:4.13.1'
testImplementation 'org.mockito:mockito-core:1.9.5'
}
android {
resourcePrefix 'zxing_'
compileSdkVersion project.androidTargetSdk
buildToolsVersion project.androidBuildTools
sourceSets {
main {
@@ -26,7 +51,7 @@ android {
res.srcDirs = ['res-orig', 'res']
assets.srcDirs = ['assets']
}
test.setRoot('test');
test.setRoot('test')
}
// This is bad practice - we should fix the warnings instead.
@@ -37,14 +62,28 @@ android {
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
testOptions {
// We test with primitives such as Rect, and rely on their default behaviour working.
unitTests.returnDefaultValues = true
}
defaultConfig {
minSdkVersion 19
}
buildTypes {
debug {
versionNameSuffix ".debug"
resValue "string", "app_version", "${defaultConfig.versionName}${versionNameSuffix}"
}
release {
resValue "string", "app_version", "${defaultConfig.versionName}"
}
}
}
task sourceJar(type: Jar) {
@@ -52,15 +91,43 @@ task sourceJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
}
publishing {
publications {
// We need this check to cover Android Studio gradle sync
if(project.tasks.findByPath('bundleRelease') != null) {
project.afterEvaluate {
publishing {
publications {
maven(MavenPublication) {
artifact bundleRelease
artifact bundleReleaseAar
artifactId project.artifactId
artifact sourceJar
pom {
name = project.artifactId
description = 'Barcode scanner library for Android, based on the ZXing decoder'
url = 'https://github.com/journeyapps/zxing-android-embedded'
licenses {
license {
name = 'The Apache License, Version 2.0'
url = 'https://github.com/journeyapps/zxing-android-embedded/blob/master/COPYING'
}
}
developers {
developer {
id = ''
name = 'Ralf Kistner'
email = 'ralf@journeyapps.com'
organization = 'Journey Mobile, Inc'
organizationUrl = 'https://journeyapps.com'
}
}
scm {
connection = 'scm:git:github.com/journeyapps/zxing-android-embedded.git'
developerConnection = 'scm:git:ssh://github.com/journeyapps/zxing-android-embedded.git'
url = 'https://github.com/journeyapps/zxing-android-embedded'
}
}
pom.withXml {
// HACK to add dependencies to POM.
@@ -68,35 +135,31 @@ publishing {
// remove this section.
def deps = asNode().appendNode('dependencies')
project.configurations.compile.allDependencies.each { dep ->
project.configurations.api.allDependencies.each { dep ->
def node = deps.appendNode('dependency')
node.appendNode('groupId', dep.group)
node.appendNode('artifactId', dep.name)
node.appendNode('version', dep.version)
node.appendNode('scope', 'compile')
node.appendNode('scope', 'api')
}
}
}
}
repositories {
maven {
name = "sonatype"
url = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
credentials {
username ossrhUsername
password ossrhPassword
}
}
}
}
}
// To release, place bintray_user and bintray_key properties in ~/.gradle/gradle.properties,
// and run ./gradlew clean assembleRelease bintrayUpload
if(project.hasProperty('bintray_user') && project.hasProperty('bintray_key')) {
bintray {
user = bintray_user
key = bintray_key
publications = ['maven']
publish = true
pkg {
userOrg = 'journeyapps'
repo = 'maven'
name = 'zxing-android-embedded'
}
}
signing {
sign publishing.publications
}
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="ResourceName,UnusedResources" >
<string name="define_zxingandroidembedded" translatable="false" />
<!-- Author section -->
<string name="library_zxingandroidembedded_author" translatable="false">JourneyApps</string>
<string name="library_zxingandroidembedded_authorWebsite" translatable="false">https://journeyapps.com/</string>
<!-- Library section -->
<string name="library_zxingandroidembedded_libraryName" translatable="false">ZXing Android Embedded</string>
<string name="library_zxingandroidembedded_libraryDescription" translatable="false">Barcode scanning library for Android, using ZXing for decoding.</string>
<string name="library_zxingandroidembedded_libraryWebsite" translatable="false">https://github.com/journeyapps/zxing-android-embedded</string>
<string name="library_zxingandroidembedded_libraryVersion" translatable="false" />
<!-- OpenSource section -->
<string name="library_zxingandroidembedded_isOpenSource" translatable="false">true</string>
<string name="library_zxingandroidembedded_repositoryLink" translatable="false">https://github.com/journeyapps/zxing-android-embedded</string>
<!-- License section -->
<string name="library_zxingandroidembedded_licenseId" translatable="false">apache_2_0</string>
<!-- Custom variables section -->
</resources>
@@ -21,6 +21,7 @@
<attr name="zxing_result_view" format="color"/>
<attr name="zxing_viewfinder_laser" format="color"/>
<attr name="zxing_viewfinder_mask" format="color"/>
<attr name="zxing_viewfinder_laser_visibility" format="boolean"/>
</declare-styleable>
</resources>
@@ -71,12 +71,7 @@ public final class AmbientLightManager implements SensorEventListener {
}
private void setTorch(final boolean on) {
handler.post(new Runnable() {
@Override
public void run() {
cameraManager.setTorch(on);
}
});
handler.post(() -> cameraManager.setTorch(on));
}
@Override
@@ -20,12 +20,13 @@ import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Vibrator;
import android.util.Log;
import java.io.Closeable;
import java.io.IOException;
/**
@@ -94,23 +95,25 @@ public final class BeepManager {
public MediaPlayer playBeepSound() {
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mp.stop();
mp.release();
}
if (Build.VERSION.SDK_INT >= 21) {
mediaPlayer.setAudioAttributes(new AudioAttributes.Builder().setContentType(
AudioAttributes.CONTENT_TYPE_MUSIC).build());
} else {
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
mediaPlayer.setOnCompletionListener(mp -> {
mp.stop();
mp.reset();
mp.release();
});
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.w(TAG, "Failed to beep " + what + ", " + extra);
// possibly media player error, so release and recreate
mp.stop();
mp.release();
return true;
}
mediaPlayer.setOnErrorListener((mp, what, extra) -> {
Log.w(TAG, "Failed to beep " + what + ", " + extra);
// possibly media player error, so release and recreate
mp.stop();
mp.reset();
mp.release();
return true;
});
try {
AssetFileDescriptor file = context.getResources().openRawResourceFd(R.raw.zxing_beep);
@@ -125,6 +128,7 @@ public final class BeepManager {
return mediaPlayer;
} catch (IOException ioe) {
Log.w(TAG, ioe);
mediaPlayer.reset();
mediaPlayer.release();
return null;
}
@@ -108,12 +108,7 @@ public final class InactivityTimer {
// 0 indicates that we're on battery
final boolean onBatteryNow = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) <= 0;
// post on handler to run in main thread
handler.post(new Runnable() {
@Override
public void run() {
onBattery(onBatteryNow);
}
});
handler.post(() -> onBattery(onBatteryNow));
}
}
}
@@ -88,6 +88,13 @@ public final class Intents {
*/
public static final String CAMERA_ID = "SCAN_CAMERA_ID";
/**
* Optional parameter to switch the torch on at camera startup.
* Enables the torch on camera startup
* If provided, should be a boolean.
*/
public static final String TORCH_ENABLED = "TORCH_ENABLED";
/**
* @see com.google.zxing.DecodeHintType#CHARACTER_SET
*/
@@ -108,6 +115,21 @@ public final class Intents {
*/
public static final String TIMEOUT = "TIMEOUT";
/**
* Set the time to finish the scan screen.
*/
public static final String MISSING_CAMERA_PERMISSION = "MISSING_CAMERA_PERMISSION";
/**
* Set the time to finish the scan screen.
*/
public static final String SHOW_MISSING_CAMERA_PERMISSION_DIALOG = "SHOW_MISSING_CAMERA_PERMISSION_DIALOG";
/**
* Set the time to finish the scan screen.
*/
public static final String MISSING_CAMERA_PERMISSION_DIALOG_MESSAGE = "MISSING_CAMERA_PERMISSION_DIALOG_MESSAGE";
/**
* Whether or not the orientation should be locked when the activity is first started.
* Defaults to true.
@@ -34,12 +34,12 @@ import java.util.List;
import java.util.Map;
/**
*
* @author Sean Owen
* @author Fred Lin
* @author Isaac Potoczny-Jones
* @author Brad Drehmer
* @author gcstang
* @deprecated Use ScanOptions and ScanContract instead.
*/
@SuppressWarnings("unused")
public class IntentIntegrator {
@@ -81,7 +81,7 @@ public class IntentIntegrator {
private final Activity activity;
private android.app.Fragment fragment;
private android.support.v4.app.Fragment supportFragment;
private androidx.fragment.app.Fragment supportFragment;
private final Map<String, Object> moreExtras = new HashMap<>(3);
@@ -137,7 +137,7 @@ public class IntentIntegrator {
* {@link #startActivityForResult(Intent, int)} will be called on the {@link Fragment} instead
* of an {@link Activity}
*/
public static IntentIntegrator forSupportFragment(android.support.v4.app.Fragment fragment) {
public static IntentIntegrator forSupportFragment(androidx.fragment.app.Fragment fragment) {
IntentIntegrator integrator = new IntentIntegrator(fragment.getActivity());
integrator.supportFragment = fragment;
return integrator;
@@ -199,6 +199,18 @@ public class IntentIntegrator {
return this;
}
/**
* Set to true to enable initial torch
*
* @param enabled true to enable initial torch
* @return this
*/
public IntentIntegrator setTorchEnabled(boolean enabled) {
addExtra(Intents.Scan.TORCH_ENABLED, enabled);
return this;
}
/**
* Set to false to disable beep on scan.
*
@@ -253,6 +265,7 @@ public class IntentIntegrator {
/**
* Initiates a scan for all known barcode types with the default camera.
* And starts a timer to finish on timeout
*
* @return Activity.RESULT_CANCELED and true on parameter TIMEOUT.
*/
public IntentIntegrator setTimeout(long timeout) {
@@ -332,7 +345,7 @@ public class IntentIntegrator {
/**
* <p>Call this from your {@link Activity}'s
* {@link Activity#onActivityResult(int, int, Intent)} method.</p>
*
* <p>
* This checks that the requestCode is equal to the default REQUEST_CODE.
*
* @param requestCode request code from {@code onActivityResult()}
@@ -341,6 +354,7 @@ public class IntentIntegrator {
* @return null if the event handled here was not related to this class, or
* else an {@link IntentResult} containing the result of the scan. If the user cancelled scanning,
* the fields will be null.
* @deprecated Not compatible with setRequestCode(). Use parseActivityResult(resultCode, intent) instead.
*/
public static IntentResult parseActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == REQUEST_CODE) {
@@ -352,8 +366,8 @@ public class IntentIntegrator {
/**
* Parse activity result, without checking the request code.
*
* @param resultCode result code from {@code onActivityResult()}
* @param intent {@link Intent} from {@code onActivityResult()}
* @param resultCode result code from {@code onActivityResult()}
* @param intent {@link Intent} from {@code onActivityResult()}
* @return an {@link IntentResult} containing the result of the scan. If the user cancelled scanning,
* the fields will be null.
*/
@@ -371,9 +385,10 @@ public class IntentIntegrator {
rawBytes,
orientation,
errorCorrectionLevel,
barcodeImagePath);
barcodeImagePath,
intent);
}
return new IntentResult();
return new IntentResult(intent);
}
private static List<String> list(String... values) {
@@ -397,6 +412,18 @@ public class IntentIntegrator {
intent.putExtra(key, (Float) value);
} else if (value instanceof Bundle) {
intent.putExtra(key, (Bundle) value);
} else if (value instanceof int[]) {
intent.putExtra(key, (int[]) value);
} else if (value instanceof long[]) {
intent.putExtra(key, (long[]) value);
} else if (value instanceof boolean[]) {
intent.putExtra(key, (boolean[]) value);
} else if (value instanceof double[]) {
intent.putExtra(key, (double[]) value);
} else if (value instanceof float[]) {
intent.putExtra(key, (float[]) value);
} else if (value instanceof String[]) {
intent.putExtra(key, (String[]) value);
} else {
intent.putExtra(key, value.toString());
}
@@ -16,6 +16,8 @@
package com.google.zxing.integration.android;
import android.content.Intent;
/**
* <p>Encapsulates the result of a barcode scan invoked through {@link IntentIntegrator}.</p>
*
@@ -29,9 +31,14 @@ public final class IntentResult {
private final Integer orientation;
private final String errorCorrectionLevel;
private final String barcodeImagePath;
private final Intent originalIntent;
IntentResult() {
this(null, null, null, null, null, null);
this(null, null, null, null, null, null, null);
}
IntentResult(Intent intent) {
this(null, null, null, null, null, null, intent);
}
IntentResult(String contents,
@@ -39,13 +46,15 @@ public final class IntentResult {
byte[] rawBytes,
Integer orientation,
String errorCorrectionLevel,
String barcodeImagePath) {
String barcodeImagePath,
Intent originalIntent) {
this.contents = contents;
this.formatName = formatName;
this.rawBytes = rawBytes;
this.orientation = orientation;
this.errorCorrectionLevel = errorCorrectionLevel;
this.barcodeImagePath = barcodeImagePath;
this.originalIntent = originalIntent;
}
/**
@@ -90,6 +99,13 @@ public final class IntentResult {
return barcodeImagePath;
}
/**
* @return the original intent
*/
public Intent getOriginalIntent() {
return originalIntent;
}
@Override
public String toString() {
int rawBytesLength = rawBytes == null ? 0 : rawBytes.length;
@@ -98,6 +114,7 @@ public final class IntentResult {
"Raw bytes: (" + rawBytesLength + " bytes)\n" +
"Orientation: " + orientation + '\n' +
"EC level: " + errorCorrectionLevel + '\n' +
"Barcode image: " + barcodeImagePath + '\n';
"Barcode image: " + barcodeImagePath + '\n' +
"Original intent: " + originalIntent + '\n';
}
}
@@ -22,7 +22,10 @@ public interface BarcodeCallback {
*
* Do not depend on this being called at any specific point in the decode cycle.
*
* This is a default method and can be omitted by the implementing class.
*
* @param resultPoints points potentially identifying a barcode
*/
void possibleResultPoints(List<ResultPoint> resultPoints);
default void possibleResultPoints(List<ResultPoint> resultPoints) {
}
}
@@ -19,13 +19,21 @@ import java.util.Map;
* Licensed under the Apache License, Version 2.0.
*/
public class BarcodeEncoder {
private static final int WHITE = 0xFFFFFFFF;
private static final int BLACK = 0xFF000000;
private int bgColor = 0xFFFFFFFF;
private int fgColor = 0xFF000000;
public BarcodeEncoder() {
}
public void setBackgroundColor(int bgColor) {
this.bgColor = bgColor;
}
public void setForegroundColor(int fgColor) {
this.fgColor = fgColor;
}
public Bitmap createBitmap(BitMatrix matrix) {
int width = matrix.getWidth();
int height = matrix.getHeight();
@@ -33,7 +41,7 @@ public class BarcodeEncoder {
for (int y = 0; y < height; y++) {
int offset = y * width;
for (int x = 0; x < width; x++) {
pixels[offset + x] = matrix.get(x, y) ? BLACK : WHITE;
pixels[offset + x] = matrix.get(x, y) ? fgColor : bgColor;
}
}
@@ -10,6 +10,10 @@ import com.google.zxing.Result;
import com.google.zxing.ResultMetadataType;
import com.google.zxing.ResultPoint;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
@@ -54,7 +58,14 @@ public class BarcodeResult {
* @see #getBitmapWithResultPoints(int)
*/
public Bitmap getBitmap() {
return sourceData.getBitmap(mScaleFactor);
return sourceData.getBitmap(null, mScaleFactor);
}
public List<ResultPoint> getTransformedResultPoints() {
if (this.mResult.getResultPoints() == null) {
return Collections.emptyList();
}
return transformResultPoints(Arrays.asList(this.mResult.getResultPoints()), this.sourceData);
}
/**
@@ -64,23 +75,23 @@ public class BarcodeResult {
public Bitmap getBitmapWithResultPoints(int color) {
Bitmap bitmap = getBitmap();
Bitmap barcode = bitmap;
ResultPoint[] points = mResult.getResultPoints();
List<ResultPoint> points = getTransformedResultPoints();
if (points != null && points.length > 0 && bitmap != null) {
if (!points.isEmpty() && bitmap != null) {
barcode = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(barcode);
canvas.drawBitmap(bitmap, 0, 0, null);
Paint paint = new Paint();
paint.setColor(color);
if (points.length == 2) {
if (points.size() == 2) {
paint.setStrokeWidth(PREVIEW_LINE_WIDTH);
drawLine(canvas, paint, points[0], points[1], mScaleFactor);
} else if (points.length == 4 &&
drawLine(canvas, paint, points.get(0), points.get(1), mScaleFactor);
} else if (points.size() == 4 &&
(mResult.getBarcodeFormat() == BarcodeFormat.UPC_A ||
mResult.getBarcodeFormat() == BarcodeFormat.EAN_13)) {
// Hacky special case -- draw two lines, for the barcode and metadata
drawLine(canvas, paint, points[0], points[1], mScaleFactor);
drawLine(canvas, paint, points[2], points[3], mScaleFactor);
drawLine(canvas, paint, points.get(0), points.get(1), mScaleFactor);
drawLine(canvas, paint, points.get(2), points.get(3), mScaleFactor);
} else {
paint.setStrokeWidth(PREVIEW_DOT_WIDTH);
for (ResultPoint point : points) {
@@ -153,4 +164,13 @@ public class BarcodeResult {
public String toString() {
return mResult.getText();
}
public static List<ResultPoint> transformResultPoints(List<ResultPoint> resultPoints, SourceData sourceData) {
List<ResultPoint> scaledPoints = new ArrayList<>(resultPoints.size());
for (ResultPoint point : resultPoints) {
scaledPoints.add(sourceData.translateResultPoint(point));
}
return scaledPoints;
}
}
@@ -197,6 +197,8 @@ public class CameraPreview extends ViewGroup {
@Override
public boolean handleMessage(Message message) {
if (message.what == R.id.zxing_prewiew_size_ready) {
// At this point, we have the camera preview size, and should have containerSize and
// surfaceRect.
previewSized((Size) message.obj);
return true;
} else if (message.what == R.id.zxing_camera_error) {
@@ -207,7 +209,7 @@ public class CameraPreview extends ViewGroup {
pause();
fireState.cameraError(error);
}
} else if(message.what == R.id.zxing_camera_closed) {
} else if (message.what == R.id.zxing_camera_closed) {
fireState.cameraClosed();
}
return false;
@@ -218,12 +220,7 @@ public class CameraPreview extends ViewGroup {
@Override
public void onRotationChanged(int rotation) {
// Make sure this is run on the main thread.
stateHandler.postDelayed(new Runnable() {
@Override
public void run() {
rotationChanged();
}
}, ROTATION_LISTENER_DELAY_MS);
stateHandler.postDelayed(() -> rotationChanged(), ROTATION_LISTENER_DELAY_MS);
}
};
@@ -269,7 +266,7 @@ public class CameraPreview extends ViewGroup {
*
* @param attrs the attributes
*/
protected void initializeAttributes(AttributeSet attrs) {
public void initializeAttributes(AttributeSet attrs) {
TypedArray styledAttributes = getContext().obtainStyledAttributes(attrs, R.styleable.zxing_camera_preview);
int framingRectWidth = (int) styledAttributes.getDimension(R.styleable.zxing_camera_preview_zxing_framing_rect_width, -1);
@@ -283,11 +280,11 @@ public class CameraPreview extends ViewGroup {
// See zxing_attrs.xml for the enum values
int scalingStrategyNumber = styledAttributes.getInteger(R.styleable.zxing_camera_preview_zxing_preview_scaling_strategy, -1);
if(scalingStrategyNumber == 1) {
if (scalingStrategyNumber == 1) {
previewScalingStrategy = new CenterCropStrategy();
} else if(scalingStrategyNumber == 2) {
} else if (scalingStrategyNumber == 2) {
previewScalingStrategy = new FitCenterStrategy();
} else if(scalingStrategyNumber == 3) {
} else if (scalingStrategyNumber == 3) {
previewScalingStrategy = new FitXYStrategy();
}
@@ -296,14 +293,14 @@ public class CameraPreview extends ViewGroup {
private void rotationChanged() {
// Confirm that it did actually change
if(isActive() && getDisplayRotation() != openedOrientation) {
if (isActive() && getDisplayRotation() != openedOrientation) {
pause();
resume();
}
}
private void setupSurfaceView() {
if(useTextureView) {
if (useTextureView) {
textureView = new TextureView(getContext());
textureView.setSurfaceTextureListener(surfaceTextureListener());
addView(textureView);
@@ -375,7 +372,13 @@ public class CameraPreview extends ViewGroup {
int width = containerSize.width;
int height = containerSize.height;
surfaceRect = displayConfiguration.scalePreview(previewSize);
Rect scaledPreview = displayConfiguration.scalePreview(previewSize);
if (scaledPreview.width() <= 0 || scaledPreview.height() <= 0) {
// Something is not ready yet - we can't start the preview.
return;
}
surfaceRect = scaledPreview;
Rect container = new Rect(0, 0, width, height);
framingRect = calculateFramingRect(container, surfaceRect);
@@ -387,7 +390,7 @@ public class CameraPreview extends ViewGroup {
frameInPreview.right * previewWidth / surfaceRect.width(),
frameInPreview.bottom * previewHeight / surfaceRect.height());
if (previewFramingRect.width() <= 0 || previewFramingRect.height() <= 0) {
if (previewFramingRect == null || previewFramingRect.width() <= 0 || previewFramingRect.height() <= 0) {
previewFramingRect = null;
framingRect = null;
Log.w(TAG, "Preview frame is too small");
@@ -428,7 +431,7 @@ public class CameraPreview extends ViewGroup {
displayConfiguration.setPreviewScalingStrategy(getPreviewScalingStrategy());
cameraInstance.setDisplayConfiguration(displayConfiguration);
cameraInstance.configureCamera();
if(torchOn) {
if (torchOn) {
cameraInstance.setTorch(torchOn);
}
}
@@ -448,14 +451,14 @@ public class CameraPreview extends ViewGroup {
* Override this to specify a different preview scaling strategy.
*/
public PreviewScalingStrategy getPreviewScalingStrategy() {
if(previewScalingStrategy != null) {
if (previewScalingStrategy != null) {
return previewScalingStrategy;
}
// If we are using SurfaceTexture, it is safe to use centerCrop.
// For SurfaceView, it's better to use fitCenter, otherwise the preview may overlap to
// other views.
if(textureView != null) {
if (textureView != null) {
return new CenterCropStrategy();
} else {
return new FitCenterStrategy();
@@ -518,8 +521,8 @@ public class CameraPreview extends ViewGroup {
if (currentSurfaceSize != null && previewSize != null && surfaceRect != null) {
if (surfaceView != null && currentSurfaceSize.equals(new Size(surfaceRect.width(), surfaceRect.height()))) {
startCameraPreview(new CameraSurface(surfaceView.getHolder()));
} else if(textureView != null && textureView.getSurfaceTexture() != null) {
if(previewSize != null) {
} else if (textureView != null && textureView.getSurfaceTexture() != null) {
if (previewSize != null) {
Matrix transform = calculateTextureTransform(new Size(textureView.getWidth(), textureView.getHeight()), previewSize);
textureView.setTransform(transform);
}
@@ -536,7 +539,7 @@ public class CameraPreview extends ViewGroup {
protected void onLayout(boolean changed, int l, int t, int r, int b) {
containerSized(new Size(r - l, b - t));
if(surfaceView != null) {
if (surfaceView != null) {
if (surfaceRect == null) {
// Match the container, to reduce the risk of issues. The preview should never be drawn
// while the surface has this size.
@@ -544,7 +547,7 @@ public class CameraPreview extends ViewGroup {
} else {
surfaceView.layout(surfaceRect.left, surfaceRect.top, surfaceRect.right, surfaceRect.bottom);
}
} else if(textureView != null) {
} else if (textureView != null) {
textureView.layout(0, 0, getWidth(), getHeight());
}
}
@@ -573,6 +576,10 @@ public class CameraPreview extends ViewGroup {
return previewFramingRect;
}
public Size getPreviewSize() {
return previewSize;
}
/**
* @return the CameraSettings currently in use
*/
@@ -610,11 +617,11 @@ public class CameraPreview extends ViewGroup {
// The activity was paused but not stopped, so the surface still exists. Therefore
// surfaceCreated() won't be called, so init the camera here.
startPreviewIfReady();
} else if(surfaceView != null) {
} else if (surfaceView != null) {
// Install the callback and wait for surfaceCreated() to init the camera.
surfaceView.getHolder().addCallback(surfaceCallback);
} else if(textureView != null) {
if(textureView.isAvailable()) {
} else if (textureView != null) {
if (textureView.isAvailable()) {
surfaceTextureListener().onSurfaceTextureAvailable(textureView.getSurfaceTexture(), textureView.getWidth(), textureView.getHeight());
} else {
textureView.setSurfaceTextureListener(surfaceTextureListener());
@@ -649,7 +656,7 @@ public class CameraPreview extends ViewGroup {
SurfaceHolder surfaceHolder = surfaceView.getHolder();
surfaceHolder.removeCallback(surfaceCallback);
}
if(currentSurfaceSize == null && textureView != null) {
if (currentSurfaceSize == null && textureView != null) {
textureView.setSurfaceTextureListener(null);
}
@@ -671,7 +678,7 @@ public class CameraPreview extends ViewGroup {
pause();
long startTime = System.nanoTime();
while(instance != null && !instance.isCameraClosed()) {
if(System.nanoTime() - startTime > 2000000000) {
if (System.nanoTime() - startTime > 2000000000) {
// Don't wait for longer than 2 seconds
break;
}
@@ -707,7 +714,7 @@ public class CameraPreview extends ViewGroup {
* @param marginFraction the fraction
*/
public void setMarginFraction(double marginFraction) {
if(marginFraction >= 0.5d) {
if (marginFraction >= 0.5d) {
throw new IllegalArgumentException("The margin fraction must be less than 0.5");
}
this.marginFraction = marginFraction;
@@ -828,7 +835,7 @@ public class CameraPreview extends ViewGroup {
Rect intersection = new Rect(container);
boolean intersects = intersection.intersect(surface);
if(framingRectSize != null) {
if (framingRectSize != null) {
// Specific size is specified. Make sure it's not larger than the container or surface.
int horizontalMargin = Math.max(0, (intersection.width() - framingRectSize.width) / 2);
int verticalMargin = Math.max(0, (intersection.height() - framingRectSize.height) / 2);
@@ -857,7 +864,7 @@ public class CameraPreview extends ViewGroup {
@Override
protected void onRestoreInstanceState(Parcelable state) {
if(!(state instanceof Bundle)) {
if (!(state instanceof Bundle)) {
super.onRestoreInstanceState(state);
return;
}
@@ -2,7 +2,7 @@ package com.journeyapps.barcodescanner;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
import android.view.KeyEvent;
import com.google.zxing.client.android.R;
@@ -4,7 +4,6 @@ import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
@@ -13,14 +12,15 @@ import android.graphics.Bitmap;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.Display;
import android.view.Surface;
import android.view.Window;
import android.view.WindowManager;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import com.google.zxing.ResultMetadataType;
import com.google.zxing.ResultPoint;
import com.google.zxing.client.android.BeepManager;
@@ -61,6 +61,9 @@ public class CaptureManager {
private static final String SAVED_ORIENTATION_LOCK = "SAVED_ORIENTATION_LOCK";
private boolean returnBarcodeImagePath = false;
private boolean showDialogIfMissingCameraPermission = true;
private String missingCameraPermissionDialogMessage = "";
private boolean destroyed = false;
private InactivityTimer inactivityTimer;
@@ -76,13 +79,7 @@ public class CaptureManager {
barcodeView.pause();
beepManager.playBeepSoundAndVibrate();
handler.post(new Runnable() {
@Override
public void run() {
returnResult(result);
}
});
handler.post(() -> returnResult(result));
}
@Override
@@ -109,12 +106,14 @@ public class CaptureManager {
@Override
public void cameraError(Exception error) {
displayFrameworkBugMessageAndExit();
displayFrameworkBugMessageAndExit(
activity.getString(R.string.zxing_msg_camera_framework_bug)
);
}
@Override
public void cameraClosed() {
if(finishWhenClosed) {
if (finishWhenClosed) {
Log.d(TAG, "Camera closed; finishing activity");
finish();
}
@@ -128,12 +127,9 @@ public class CaptureManager {
handler = new Handler();
inactivityTimer = new InactivityTimer(activity, new Runnable() {
@Override
public void run() {
Log.d(TAG, "Finishing due to inactivity");
finish();
}
inactivityTimer = new InactivityTimer(activity, () -> {
Log.d(TAG, "Finishing due to inactivity");
finish();
});
beepManager = new BeepManager(activity);
@@ -156,7 +152,7 @@ public class CaptureManager {
this.orientationLock = savedInstanceState.getInt(SAVED_ORIENTATION_LOCK, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
if(intent != null) {
if (intent != null) {
// Only lock the orientation if it's not locked to something else yet
boolean orientationLocked = intent.getBooleanExtra(Intents.Scan.ORIENTATION_LOCKED, true);
if (orientationLocked) {
@@ -171,14 +167,15 @@ public class CaptureManager {
beepManager.setBeepEnabled(false);
}
if (intent.hasExtra(Intents.Scan.SHOW_MISSING_CAMERA_PERMISSION_DIALOG)) {
setShowMissingCameraPermissionDialog(
intent.getBooleanExtra(Intents.Scan.SHOW_MISSING_CAMERA_PERMISSION_DIALOG, true),
intent.getStringExtra(Intents.Scan.MISSING_CAMERA_PERMISSION_DIALOG_MESSAGE)
);
}
if (intent.hasExtra(Intents.Scan.TIMEOUT)) {
Runnable runnable = new Runnable() {
@Override
public void run() {
returnResultTimeout();
}
};
handler.postDelayed(runnable, intent.getLongExtra(Intents.Scan.TIMEOUT, 0L));
handler.postDelayed(this::returnResultTimeout, intent.getLongExtra(Intents.Scan.TIMEOUT, 0L));
}
if (intent.getBooleanExtra(Intents.Scan.BARCODE_IMAGE_ENABLED, false)) {
@@ -229,7 +226,7 @@ public class CaptureManager {
* Call from Activity#onResume().
*/
public void onResume() {
if(Build.VERSION.SDK_INT >= 23) {
if (Build.VERSION.SDK_INT >= 23) {
openCameraWithPermission();
} else {
barcodeView.resume();
@@ -244,32 +241,35 @@ public class CaptureManager {
if (ContextCompat.checkSelfPermission(this.activity, Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED) {
barcodeView.resume();
} else if(!askedPermission) {
} else if (!askedPermission) {
ActivityCompat.requestPermissions(this.activity,
new String[]{Manifest.permission.CAMERA},
cameraPermissionReqCode);
askedPermission = true;
} else {
// Wait for permission result
}
} // else wait for permission result
}
/**
* Call from Activity#onRequestPermissionsResult
* @param requestCode The request code passed in {@link android.support.v4.app.ActivityCompat#requestPermissions(Activity, String[], int)}.
* @param requestCode The request code passed in {@link androidx.core.app.ActivityCompat#requestPermissions(Activity, String[], int)}.
* @param permissions The requested permissions.
* @param grantResults The grant results for the corresponding permissions
* which is either {@link android.content.pm.PackageManager#PERMISSION_GRANTED}
* or {@link android.content.pm.PackageManager#PERMISSION_DENIED}. Never null.
*/
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
if(requestCode == cameraPermissionReqCode) {
if (requestCode == cameraPermissionReqCode) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted
barcodeView.resume();
} else {
// TODO: display better error message.
displayFrameworkBugMessageAndExit();
setMissingCameraPermissionResult();
if (showDialogIfMissingCameraPermission) {
displayFrameworkBugMessageAndExit(missingCameraPermissionDialogMessage);
} else {
closeAndFinish();
}
}
}
}
@@ -374,7 +374,7 @@ public class CaptureManager {
}
protected void closeAndFinish() {
if(barcodeView.getBarcodeView().isCameraClosed()) {
if (barcodeView.getBarcodeView().isCameraClosed()) {
finish();
} else {
finishWhenClosed = true;
@@ -384,6 +384,12 @@ public class CaptureManager {
inactivityTimer.cancel();
}
private void setMissingCameraPermissionResult() {
Intent intent = new Intent(Intents.Scan.ACTION);
intent.putExtra(Intents.Scan.MISSING_CAMERA_PERMISSION, true);
activity.setResult(Activity.RESULT_CANCELED, intent);
}
protected void returnResultTimeout() {
Intent intent = new Intent(Intents.Scan.ACTION);
intent.putExtra(Intents.Scan.TIMEOUT, true);
@@ -397,25 +403,20 @@ public class CaptureManager {
closeAndFinish();
}
protected void displayFrameworkBugMessageAndExit() {
protected void displayFrameworkBugMessageAndExit(String message) {
if (activity.isFinishing() || this.destroyed || finishWhenClosed) {
return;
}
if (message.isEmpty()) {
message = activity.getString(R.string.zxing_msg_camera_framework_bug);
}
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(activity.getString(R.string.zxing_app_name));
builder.setMessage(activity.getString(R.string.zxing_msg_camera_framework_bug));
builder.setPositiveButton(R.string.zxing_button_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
finish();
}
});
builder.setMessage(message);
builder.setPositiveButton(R.string.zxing_button_ok, (dialog, which) -> finish());
builder.setOnCancelListener(dialog -> finish());
builder.show();
}
@@ -426,4 +427,29 @@ public class CaptureManager {
public static void setCameraPermissionReqCode(int cameraPermissionReqCode) {
CaptureManager.cameraPermissionReqCode = cameraPermissionReqCode;
}
/**
* If set to true, shows the default error dialog if camera permission is missing.
* <p>
* If set to false, instead the capture manager just finishes.
* <p>
* In both cases, the activity result is set to {@link Intents.Scan#MISSING_CAMERA_PERMISSION}
* and cancelled
*/
public void setShowMissingCameraPermissionDialog(boolean visible) {
setShowMissingCameraPermissionDialog(visible, "");
}
/**
* If set to true, shows the specified error dialog message if camera permission is missing.
* <p>
* If set to false, instead the capture manager just finishes.
* <p>
* In both cases, the activity result is set to {@link Intents.Scan#MISSING_CAMERA_PERMISSION}
* and cancelled
*/
public void setShowMissingCameraPermissionDialog(boolean visible, String message) {
showDialogIfMissingCameraPermission = visible;
missingCameraPermissionDialogMessage = message != null ? message : "";
}
}
@@ -26,7 +26,7 @@ public class DecoderResultPointCallback implements ResultPointCallback {
@Override
public void foundPossibleResultPoint(ResultPoint point) {
if(decoder != null) {
if (decoder != null) {
decoder.foundPossibleResultPoint(point);
}
}
@@ -36,7 +36,7 @@ public class DecoderThread {
public boolean handleMessage(Message message) {
if (message.what == R.id.zxing_decode) {
decode((SourceData) message.obj);
} else if(message.what == R.id.zxing_preview_failed) {
} else if (message.what == R.id.zxing_preview_failed) {
// Error already logged. Try again.
requestNextPreview();
}
@@ -142,7 +142,7 @@ public class DecoderThread {
sourceData.setCropRect(cropRect);
LuminanceSource source = createSource(sourceData);
if(source != null) {
if (source != null) {
rawResult = decoder.decode(source);
}
@@ -164,8 +164,8 @@ public class DecoderThread {
}
}
if (resultHandler != null) {
List<ResultPoint> resultPoints = decoder.getPossibleResultPoints();
Message message = Message.obtain(resultHandler, R.id.zxing_possible_result_points, resultPoints);
List<ResultPoint> resultPoints = BarcodeResult.transformResultPoints(decoder.getPossibleResultPoints(), sourceData);
Message message = Message.obtain(resultHandler, R.id.zxing_possible_result_points, resultPoints);
message.sendToTarget();
}
requestNextPreview();
@@ -90,7 +90,7 @@ public class DecoratedBarcodeView extends FrameLayout {
inflate(getContext(), scannerLayout, this);
barcodeView = (BarcodeView) findViewById(R.id.zxing_barcode_surface);
barcodeView = findViewById(R.id.zxing_barcode_surface);
if (barcodeView == null) {
throw new IllegalArgumentException(
@@ -102,7 +102,7 @@ public class DecoratedBarcodeView extends FrameLayout {
barcodeView.initializeAttributes(attrs);
viewFinder = (ViewfinderView) findViewById(R.id.zxing_viewfinder_view);
viewFinder = findViewById(R.id.zxing_viewfinder_view);
if (viewFinder == null) {
throw new IllegalArgumentException(
@@ -113,11 +113,11 @@ public class DecoratedBarcodeView extends FrameLayout {
viewFinder.setCameraPreview(barcodeView);
// statusView is optional
statusView = (TextView) findViewById(R.id.zxing_status_view);
statusView = findViewById(R.id.zxing_status_view);
}
/**
* Initialize with no custom attributes setted.
* Initialize with no custom attributes set.
*/
private void initialize() {
initialize(null);
@@ -142,6 +142,12 @@ public class DecoratedBarcodeView extends FrameLayout {
}
}
if (intent.hasExtra(Intents.Scan.TORCH_ENABLED)) {
if (intent.getBooleanExtra(Intents.Scan.TORCH_ENABLED, false)) {
this.setTorchOn();
}
}
String customPromptMessage = intent.getStringExtra(Intents.Scan.PROMPT_MESSAGE);
if (customPromptMessage != null) {
setStatusText(customPromptMessage);
@@ -159,9 +165,25 @@ public class DecoratedBarcodeView extends FrameLayout {
barcodeView.setDecoderFactory(new DefaultDecoderFactory(decodeFormats, decodeHints, characterSet, scanType));
}
public void setCameraSettings(CameraSettings cameraSettings) {
barcodeView.setCameraSettings(cameraSettings);
}
public void setDecoderFactory(DecoderFactory decoderFactory) {
barcodeView.setDecoderFactory(decoderFactory);
}
public DecoderFactory getDecoderFactory() {
return barcodeView.getDecoderFactory();
}
public CameraSettings getCameraSettings() {
return barcodeView.getCameraSettings();
}
public void setStatusText(String text) {
// statusView is optional when using a custom layout
if(statusView != null) {
if (statusView != null) {
statusView.setText(text);
}
}
@@ -188,7 +210,7 @@ public class DecoratedBarcodeView extends FrameLayout {
}
public BarcodeView getBarcodeView() {
return (BarcodeView) findViewById(R.id.zxing_barcode_surface);
return findViewById(R.id.zxing_barcode_surface);
}
public ViewfinderView getViewFinder() {
@@ -39,11 +39,11 @@ public class DefaultDecoderFactory implements DecoderFactory {
hints.putAll(baseHints);
if(this.hints != null) {
if (this.hints != null) {
hints.putAll(this.hints);
}
if(this.decodeFormats != null) {
if (this.decodeFormats != null) {
hints.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormats);
}
@@ -0,0 +1,142 @@
package com.journeyapps.barcodescanner;
import android.graphics.Rect;
public class RawImageData {
private byte[] data;
private int width;
private int height;
public RawImageData(byte[] data, int width, int height) {
this.data = data;
this.width = width;
this.height = height;
}
public byte[] getData() {
return data;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public RawImageData cropAndScale(Rect cropRect, int scale) {
int width = cropRect.width() / scale;
int height = cropRect.height() / scale;
int top = cropRect.top;
int area = width * height;
byte[] matrix = new byte[area];
if (scale == 1) {
int inputOffset = top * this.width + cropRect.left;
// Copy one cropped row at a time.
for (int y = 0; y < height; y++) {
int outputOffset = y * width;
System.arraycopy(this.data, inputOffset, matrix, outputOffset, width);
inputOffset += this.width;
}
} else {
int inputOffset = top * this.width + cropRect.left;
// Copy one cropped row at a time.
for (int y = 0; y < height; y++) {
int outputOffset = y * width;
int xOffset = inputOffset;
for (int x = 0; x < width; x++) {
matrix[outputOffset] = this.data[xOffset];
xOffset += scale;
outputOffset += 1;
}
inputOffset += this.width * scale;
}
}
return new RawImageData(matrix, width, height);
}
public RawImageData rotateCameraPreview(int cameraRotation) {
switch (cameraRotation) {
case 90:
return new RawImageData(rotateCW(data, this.width, this.height), this.height, this.width);
case 180:
return new RawImageData(rotate180(data, this.width, this.height), this.width, this.height);
case 270:
return new RawImageData(rotateCCW(data, this.width, this.height), this.height, this.width);
case 0:
default:
return this;
}
}
/**
* Rotate an image by 90 degrees CW.
*
* @param data the image data, in with the first width * height bytes being the luminance data.
* @param imageWidth the width of the image
* @param imageHeight the height of the image
* @return the rotated bytes
*/
public static byte[] rotateCW(byte[] data, int imageWidth, int imageHeight) {
// Adapted from http://stackoverflow.com/a/15775173
// data may contain more than just y (u and v), but we are only interested in the y section.
byte[] yuv = new byte[imageWidth * imageHeight];
int i = 0;
for (int x = 0; x < imageWidth; x++) {
for (int y = imageHeight - 1; y >= 0; y--) {
yuv[i] = data[y * imageWidth + x];
i++;
}
}
return yuv;
}
/**
* Rotate an image by 180 degrees.
*
* @param data the image data, in with the first width * height bytes being the luminance data.
* @param imageWidth the width of the image
* @param imageHeight the height of the image
* @return the rotated bytes
*/
public static byte[] rotate180(byte[] data, int imageWidth, int imageHeight) {
int n = imageWidth * imageHeight;
byte[] yuv = new byte[n];
int i = n - 1;
for (int j = 0; j < n; j++) {
yuv[i] = data[j];
i--;
}
return yuv;
}
/**
* Rotate an image by 90 degrees CCW.
*
* @param data the image data, in with the first width * height bytes being the luminance data.
* @param imageWidth the width of the image
* @param imageHeight the height of the image
* @return the rotated bytes
*/
public static byte[] rotateCCW(byte[] data, int imageWidth, int imageHeight) {
int n = imageWidth * imageHeight;
byte[] yuv = new byte[n];
int i = n - 1;
for (int x = 0; x < imageWidth; x++) {
for (int y = imageHeight - 1; y >= 0; y--) {
yuv[i] = data[y * imageWidth + x];
i--;
}
}
return yuv;
}
}
@@ -40,7 +40,7 @@ public class RotationListener {
public void onOrientationChanged(int orientation) {
WindowManager localWindowManager = windowManager;
RotationCallback localCallback = RotationListener.this.callback;
if(windowManager != null && localCallback != null) {
if (windowManager != null && localCallback != null) {
int newRotation = localWindowManager.getDefaultDisplay().getRotation();
if (newRotation != lastRotation) {
lastRotation = newRotation;
@@ -57,7 +57,7 @@ public class RotationListener {
public void stop() {
// To reduce the effect of possible leaks, we clear any references we have to external
// objects.
if(this.orientationEventListener != null) {
if (this.orientationEventListener != null) {
this.orientationEventListener.disable();
}
this.orientationEventListener = null;
@@ -0,0 +1,21 @@
package com.journeyapps.barcodescanner;
import android.content.Context;
import android.content.Intent;
import androidx.activity.result.contract.ActivityResultContract;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class ScanContract extends ActivityResultContract<ScanOptions, ScanIntentResult> {
@NonNull
@Override
public Intent createIntent(@NonNull Context context, ScanOptions input) {
return input.createScanIntent(context);
}
@Override
public ScanIntentResult parseResult(int resultCode, @Nullable Intent intent) {
return ScanIntentResult.parseActivityResult(resultCode, intent);
}
}
@@ -0,0 +1,155 @@
/*
* Based on IntentResult.
*
* Copyright 2009 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.journeyapps.barcodescanner;
import android.app.Activity;
import android.content.Intent;
import com.google.zxing.client.android.Intents;
import com.google.zxing.integration.android.IntentResult;
/**
* <p>Encapsulates the result of a barcode scan invoked through {@link ScanContract}.</p>
*
* @author Sean Owen
*/
public final class ScanIntentResult {
private final String contents;
private final String formatName;
private final byte[] rawBytes;
private final Integer orientation;
private final String errorCorrectionLevel;
private final String barcodeImagePath;
private final Intent originalIntent;
ScanIntentResult() {
this(null, null, null, null, null, null, null);
}
ScanIntentResult(Intent intent) {
this(null, null, null, null, null, null, intent);
}
ScanIntentResult(String contents,
String formatName,
byte[] rawBytes,
Integer orientation,
String errorCorrectionLevel,
String barcodeImagePath,
Intent originalIntent) {
this.contents = contents;
this.formatName = formatName;
this.rawBytes = rawBytes;
this.orientation = orientation;
this.errorCorrectionLevel = errorCorrectionLevel;
this.barcodeImagePath = barcodeImagePath;
this.originalIntent = originalIntent;
}
/**
* @return raw content of barcode
*/
public String getContents() {
return contents;
}
/**
* @return name of format, like "QR_CODE", "UPC_A". See {@code BarcodeFormat} for more format names.
*/
public String getFormatName() {
return formatName;
}
/**
* @return raw bytes of the barcode content, if applicable, or null otherwise
*/
public byte[] getRawBytes() {
return rawBytes;
}
/**
* @return rotation of the image, in degrees, which resulted in a successful scan. May be null.
*/
public Integer getOrientation() {
return orientation;
}
/**
* @return name of the error correction level used in the barcode, if applicable
*/
public String getErrorCorrectionLevel() {
return errorCorrectionLevel;
}
/**
* @return path to a temporary file containing the barcode image, if applicable, or null otherwise
*/
public String getBarcodeImagePath() {
return barcodeImagePath;
}
/**
* @return the original intent
*/
public Intent getOriginalIntent() {
return originalIntent;
}
@Override
public String toString() {
int rawBytesLength = rawBytes == null ? 0 : rawBytes.length;
return "Format: " + formatName + '\n' +
"Contents: " + contents + '\n' +
"Raw bytes: (" + rawBytesLength + " bytes)\n" +
"Orientation: " + orientation + '\n' +
"EC level: " + errorCorrectionLevel + '\n' +
"Barcode image: " + barcodeImagePath + '\n' +
"Original intent: " + originalIntent + '\n';
}
/**
* Parse activity result, without checking the request code.
*
* @param resultCode result code from {@code onActivityResult()}
* @param intent {@link Intent} from {@code onActivityResult()}
* @return an {@link IntentResult} containing the result of the scan. If the user cancelled scanning,
* the fields will be null.
*/
public static ScanIntentResult parseActivityResult(int resultCode, Intent intent) {
if (resultCode == Activity.RESULT_OK) {
String contents = intent.getStringExtra(Intents.Scan.RESULT);
String formatName = intent.getStringExtra(Intents.Scan.RESULT_FORMAT);
byte[] rawBytes = intent.getByteArrayExtra(Intents.Scan.RESULT_BYTES);
int intentOrientation = intent.getIntExtra(Intents.Scan.RESULT_ORIENTATION, Integer.MIN_VALUE);
Integer orientation = intentOrientation == Integer.MIN_VALUE ? null : intentOrientation;
String errorCorrectionLevel = intent.getStringExtra(Intents.Scan.RESULT_ERROR_CORRECTION_LEVEL);
String barcodeImagePath = intent.getStringExtra(Intents.Scan.RESULT_BARCODE_IMAGE_PATH);
return new ScanIntentResult(contents,
formatName,
rawBytes,
orientation,
errorCorrectionLevel,
barcodeImagePath,
intent);
}
return new ScanIntentResult(intent);
}
}
@@ -0,0 +1,262 @@
/*
* Based on IntentIntegrator, Copyright 2009 ZXing authors.
*
*/
package com.journeyapps.barcodescanner;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import com.google.zxing.client.android.Intents;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ScanOptions {
// supported barcode formats
// Product Codes
public static final String UPC_A = "UPC_A";
public static final String UPC_E = "UPC_E";
public static final String EAN_8 = "EAN_8";
public static final String EAN_13 = "EAN_13";
public static final String RSS_14 = "RSS_14";
// Other 1D
public static final String CODE_39 = "CODE_39";
public static final String CODE_93 = "CODE_93";
public static final String CODE_128 = "CODE_128";
public static final String ITF = "ITF";
public static final String RSS_EXPANDED = "RSS_EXPANDED";
// 2D
public static final String QR_CODE = "QR_CODE";
public static final String DATA_MATRIX = "DATA_MATRIX";
public static final String PDF_417 = "PDF_417";
public static final Collection<String> PRODUCT_CODE_TYPES = list(UPC_A, UPC_E, EAN_8, EAN_13, RSS_14);
public static final Collection<String> ONE_D_CODE_TYPES =
list(UPC_A, UPC_E, EAN_8, EAN_13, RSS_14, CODE_39, CODE_93, CODE_128,
ITF, RSS_14, RSS_EXPANDED);
public static final Collection<String> ALL_CODE_TYPES = null;
private final Map<String, Object> moreExtras = new HashMap<>(3);
private Collection<String> desiredBarcodeFormats;
private Class<?> captureActivity;
protected Class<?> getDefaultCaptureActivity() {
return CaptureActivity.class;
}
public ScanOptions() {
}
public Class<?> getCaptureActivity() {
if (captureActivity == null) {
captureActivity = getDefaultCaptureActivity();
}
return captureActivity;
}
/**
* Set the Activity class to use. It can be any activity, but should handle the intent extras
* as used here.
*
* @param captureActivity the class
*/
public ScanOptions setCaptureActivity(Class<?> captureActivity) {
this.captureActivity = captureActivity;
return this;
}
public Map<String, ?> getMoreExtras() {
return moreExtras;
}
public final ScanOptions addExtra(String key, Object value) {
moreExtras.put(key, value);
return this;
}
/**
* Set a prompt to display on the capture screen, instead of using the default.
*
* @param prompt the prompt to display
*/
public final ScanOptions setPrompt(String prompt) {
if (prompt != null) {
addExtra(Intents.Scan.PROMPT_MESSAGE, prompt);
}
return this;
}
/**
* By default, the orientation is locked. Set to false to not lock.
*
* @param locked true to lock orientation
*/
public ScanOptions setOrientationLocked(boolean locked) {
addExtra(Intents.Scan.ORIENTATION_LOCKED, locked);
return this;
}
/**
* Use the specified camera ID.
*
* @param cameraId camera ID of the camera to use. A negative value means "no preference".
* @return this
*/
public ScanOptions setCameraId(int cameraId) {
if (cameraId >= 0) {
addExtra(Intents.Scan.CAMERA_ID, cameraId);
}
return this;
}
/**
* Set to true to enable initial torch
*
* @param enabled true to enable initial torch
* @return this
*/
public ScanOptions setTorchEnabled(boolean enabled) {
addExtra(Intents.Scan.TORCH_ENABLED, enabled);
return this;
}
/**
* Set to false to disable beep on scan.
*
* @param enabled false to disable beep
* @return this
*/
public ScanOptions setBeepEnabled(boolean enabled) {
addExtra(Intents.Scan.BEEP_ENABLED, enabled);
return this;
}
/**
* Set to true to enable saving the barcode image and sending its path in the result Intent.
*
* @param enabled true to enable barcode image
* @return this
*/
public ScanOptions setBarcodeImageEnabled(boolean enabled) {
addExtra(Intents.Scan.BARCODE_IMAGE_ENABLED, enabled);
return this;
}
/**
* Set the desired barcode formats to scan.
*
* @param desiredBarcodeFormats names of {@code BarcodeFormat}s to scan for
* @return this
*/
public ScanOptions setDesiredBarcodeFormats(Collection<String> desiredBarcodeFormats) {
this.desiredBarcodeFormats = desiredBarcodeFormats;
return this;
}
/**
* Set the desired barcode formats to scan.
*
* @param desiredBarcodeFormats names of {@code BarcodeFormat}s to scan for
* @return this
*/
public ScanOptions setDesiredBarcodeFormats(String... desiredBarcodeFormats) {
this.desiredBarcodeFormats = Arrays.asList(desiredBarcodeFormats);
return this;
}
/**
* Initiates a scan for all known barcode types with the default camera.
* And starts a timer to finish on timeout
*
* @return Activity.RESULT_CANCELED and true on parameter TIMEOUT.
*/
public ScanOptions setTimeout(long timeout) {
addExtra(Intents.Scan.TIMEOUT, timeout);
return this;
}
/**
* Create an scan intent with the specified options.
*
* @return the intent
*/
public Intent createScanIntent(Context context) {
Intent intentScan = new Intent(context, getCaptureActivity());
intentScan.setAction(Intents.Scan.ACTION);
// check which types of codes to scan for
if (desiredBarcodeFormats != null) {
// set the desired barcode types
StringBuilder joinedByComma = new StringBuilder();
for (String format : desiredBarcodeFormats) {
if (joinedByComma.length() > 0) {
joinedByComma.append(',');
}
joinedByComma.append(format);
}
intentScan.putExtra(Intents.Scan.FORMATS, joinedByComma.toString());
}
intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
attachMoreExtras(intentScan);
return intentScan;
}
private static List<String> list(String... values) {
return Collections.unmodifiableList(Arrays.asList(values));
}
private void attachMoreExtras(Intent intent) {
for (Map.Entry<String, Object> entry : moreExtras.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
// Kind of hacky
if (value instanceof Integer) {
intent.putExtra(key, (Integer) value);
} else if (value instanceof Long) {
intent.putExtra(key, (Long) value);
} else if (value instanceof Boolean) {
intent.putExtra(key, (Boolean) value);
} else if (value instanceof Double) {
intent.putExtra(key, (Double) value);
} else if (value instanceof Float) {
intent.putExtra(key, (Float) value);
} else if (value instanceof Bundle) {
intent.putExtra(key, (Bundle) value);
} else if (value instanceof int[]) {
intent.putExtra(key, (int[]) value);
} else if (value instanceof long[]) {
intent.putExtra(key, (long[]) value);
} else if (value instanceof boolean[]) {
intent.putExtra(key, (boolean[]) value);
} else if (value instanceof double[]) {
intent.putExtra(key, (double[]) value);
} else if (value instanceof float[]) {
intent.putExtra(key, (float[]) value);
} else if (value instanceof String[]) {
intent.putExtra(key, (String[]) value);
} else {
intent.putExtra(key, value.toString());
}
}
}
}
@@ -1,6 +1,6 @@
package com.journeyapps.barcodescanner;
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
/**
*
@@ -43,7 +43,7 @@ public class Size implements Comparable<Size> {
* @return the scaled size
*/
public Size scaleFit(Size into) {
if(width * into.height >= into.width * height) {
if (width * into.height >= into.width * height) {
// match width
return new Size(into.width, height * into.width / width);
} else {
@@ -59,7 +59,7 @@ public class Size implements Comparable<Size> {
* @return the scaled size
*/
public Size scaleCrop(Size into) {
if(width * into.height <= into.width * height) {
if (width * into.height <= into.width * height) {
// match width
return new Size(into.width, height * into.width / width);
} else {
@@ -2,12 +2,12 @@ package com.journeyapps.barcodescanner;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.YuvImage;
import com.google.zxing.PlanarYUVLuminanceSource;
import com.google.zxing.ResultPoint;
import java.io.ByteArrayOutputStream;
@@ -15,14 +15,7 @@ import java.io.ByteArrayOutputStream;
* Raw preview data from a camera.
*/
public class SourceData {
/** Raw YUV data */
private byte[] data;
/** Source data width */
private int dataWidth;
/** Source data height */
private int dataHeight;
private RawImageData data;
/** The format of the image data. ImageFormat.NV21 and ImageFormat.YUY2 are supported. */
private int imageFormat;
@@ -33,6 +26,13 @@ public class SourceData {
/** Crop rectangle, in display orientation. */
private Rect cropRect;
/**
* Factor by which to scale down before decoding.
*/
private int scalingFactor = 1;
private boolean previewMirrored;
/**
*
* @param data the image data
@@ -42,15 +42,12 @@ public class SourceData {
* @param rotation camera rotation relative to display rotation, in degrees (0, 90, 180 or 270).
*/
public SourceData(byte[] data, int dataWidth, int dataHeight, int imageFormat, int rotation) {
this.data = data;
this.dataWidth = dataWidth;
this.dataHeight = dataHeight;
this.data = new RawImageData(data, dataWidth, dataHeight);
this.rotation = rotation;
this.imageFormat = imageFormat;
if(dataWidth * dataHeight > data.length) {
if (dataWidth * dataHeight > data.length) {
throw new IllegalArgumentException("Image data does not match the resolution. " + dataWidth + "x" + dataHeight + " > " + data.length);
}
}
public Rect getCropRect() {
@@ -66,8 +63,24 @@ public class SourceData {
this.cropRect = cropRect;
}
public boolean isPreviewMirrored() {
return previewMirrored;
}
public void setPreviewMirrored(boolean previewMirrored) {
this.previewMirrored = previewMirrored;
}
public int getScalingFactor() {
return scalingFactor;
}
public void setScalingFactor(int scalingFactor) {
this.scalingFactor = scalingFactor;
}
public byte[] getData() {
return data;
return data.getData();
}
/**
@@ -75,7 +88,7 @@ public class SourceData {
* @return width of the data
*/
public int getDataWidth() {
return dataWidth;
return data.getWidth();
}
/**
@@ -83,7 +96,16 @@ public class SourceData {
* @return height of the data
*/
public int getDataHeight() {
return dataHeight;
return data.getHeight();
}
public ResultPoint translateResultPoint(ResultPoint point) {
float x = point.getX() * this.scalingFactor + this.cropRect.left;
float y = point.getY() * this.scalingFactor + this.cropRect.top;
if (previewMirrored) {
x = data.getWidth() - x;
}
return new ResultPoint(x, y);
}
/**
@@ -99,15 +121,11 @@ public class SourceData {
}
public PlanarYUVLuminanceSource createSource() {
byte[] rotated = rotateCameraPreview(rotation, data, dataWidth, dataHeight);
// TODO: handle mirrored (front) camera. Probably only the ResultPoints should be mirrored,
RawImageData rotated = this.data.rotateCameraPreview(rotation);
RawImageData scaled = rotated.cropAndScale(this.cropRect, this.scalingFactor);
// not the preview for decoding.
if (isRotated()) {
//noinspection SuspiciousNameCombination
return new PlanarYUVLuminanceSource(rotated, dataHeight, dataWidth, cropRect.left, cropRect.top, cropRect.width(), cropRect.height(), false);
} else {
return new PlanarYUVLuminanceSource(rotated, dataWidth, dataHeight, cropRect.left, cropRect.top, cropRect.width(), cropRect.height(), false);
}
return new PlanarYUVLuminanceSource(scaled.getData(), scaled.getWidth(), scaled.getHeight(), 0, 0, scaled.getWidth(), scaled.getHeight(), false);
}
/**
@@ -129,14 +147,16 @@ public class SourceData {
return getBitmap(cropRect, scaleFactor);
}
private Bitmap getBitmap(Rect cropRect, int scaleFactor) {
if(isRotated()) {
public Bitmap getBitmap(Rect cropRect, int scaleFactor) {
if (cropRect == null) {
cropRect = new Rect(0, 0, data.getWidth(), data.getHeight());
} else if (isRotated()) {
//noinspection SuspiciousNameCombination
cropRect = new Rect(cropRect.top, cropRect.left, cropRect.bottom, cropRect.right);
}
// TODO: there should be a way to do this without JPEG compression / decompression cycle.
YuvImage img = new YuvImage(data, imageFormat, dataWidth, dataHeight, null);
YuvImage img = new YuvImage(data.getData(), imageFormat, data.getWidth(), data.getHeight(), null);
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
img.compressToJpeg(cropRect, 90, buffer);
byte[] jpegData = buffer.toByteArray();
@@ -155,83 +175,4 @@ public class SourceData {
return bitmap;
}
public static byte[] rotateCameraPreview(int cameraRotation, byte[] data, int imageWidth, int imageHeight) {
switch (cameraRotation) {
case 0:
return data;
case 90:
return rotateCW(data, imageWidth, imageHeight);
case 180:
return rotate180(data, imageWidth, imageHeight);
case 270:
return rotateCCW(data, imageWidth, imageHeight);
default:
// Should not happen
return data;
}
}
/**
* Rotate an image by 90 degrees CW.
*
* @param data the image data, in with the first width * height bytes being the luminance data.
* @param imageWidth the width of the image
* @param imageHeight the height of the image
* @return the rotated bytes
*/
public static byte[] rotateCW(byte[] data, int imageWidth, int imageHeight) {
// Adapted from http://stackoverflow.com/a/15775173
// data may contain more than just y (u and v), but we are only interested in the y section.
byte[] yuv = new byte[imageWidth * imageHeight];
int i = 0;
for (int x = 0; x < imageWidth; x++) {
for (int y = imageHeight - 1; y >= 0; y--) {
yuv[i] = data[y * imageWidth + x];
i++;
}
}
return yuv;
}
/**
* Rotate an image by 180 degrees.
*
* @param data the image data, in with the first width * height bytes being the luminance data.
* @param imageWidth the width of the image
* @param imageHeight the height of the image
* @return the rotated bytes
*/
public static byte[] rotate180(byte[] data, int imageWidth, int imageHeight) {
int n = imageWidth * imageHeight;
byte[] yuv = new byte[n];
int i = n - 1;
for (int j = 0; j < n; j++) {
yuv[i] = data[j];
i--;
}
return yuv;
}
/**
* Rotate an image by 90 degrees CCW.
*
* @param data the image data, in with the first width * height bytes being the luminance data.
* @param imageWidth the width of the image
* @param imageHeight the height of the image
* @return the rotated bytes
*/
public static byte[] rotateCCW(byte[] data, int imageWidth, int imageHeight) {
int n = imageWidth * imageHeight;
byte[] yuv = new byte[n];
int i = n - 1;
for (int x = 0; x < imageWidth; x++) {
for (int y = imageHeight - 1; y >= 0; y--) {
yuv[i] = data[y * imageWidth + x];
i--;
}
}
return yuv;
}
}
@@ -16,7 +16,6 @@
package com.journeyapps.barcodescanner;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -50,19 +49,20 @@ public class ViewfinderView extends View {
protected final Paint paint;
protected Bitmap resultBitmap;
protected final int maskColor;
protected int maskColor;
protected final int resultColor;
protected final int laserColor;
protected final int resultPointColor;
protected boolean laserVisibility;
protected int scannerAlpha;
protected List<ResultPoint> possibleResultPoints;
protected List<ResultPoint> lastPossibleResultPoints;
protected CameraPreview cameraPreview;
// Cache the framingRect and previewFramingRect, so that we can still draw it after the preview
// Cache the framingRect and previewSize, so that we can still draw it after the preview
// stopped.
protected Rect framingRect;
protected Rect previewFramingRect;
protected Size previewSize;
// This constructor is used when the class is built from an XML resource.
public ViewfinderView(Context context, AttributeSet attrs) {
@@ -73,7 +73,7 @@ public class ViewfinderView extends View {
Resources resources = getResources();
// Get setted attributes on view
// Get set attributes on view
TypedArray attributes = getContext().obtainStyledAttributes(attrs, R.styleable.zxing_finder);
this.maskColor = attributes.getColor(R.styleable.zxing_finder_zxing_viewfinder_mask,
@@ -84,6 +84,8 @@ public class ViewfinderView extends View {
resources.getColor(R.color.zxing_viewfinder_laser));
this.resultPointColor = attributes.getColor(R.styleable.zxing_finder_zxing_possible_result_points,
resources.getColor(R.color.zxing_possible_result_points));
this.laserVisibility = attributes.getBoolean(R.styleable.zxing_finder_zxing_viewfinder_laser_visibility,
true);
attributes.recycle();
@@ -124,29 +126,29 @@ public class ViewfinderView extends View {
}
protected void refreshSizes() {
if(cameraPreview == null) {
if (cameraPreview == null) {
return;
}
Rect framingRect = cameraPreview.getFramingRect();
Rect previewFramingRect = cameraPreview.getPreviewFramingRect();
if(framingRect != null && previewFramingRect != null) {
Size previewSize = cameraPreview.getPreviewSize();
if (framingRect != null && previewSize != null) {
this.framingRect = framingRect;
this.previewFramingRect = previewFramingRect;
this.previewSize = previewSize;
}
}
@Override
public void onDraw(Canvas canvas) {
refreshSizes();
if (framingRect == null || previewFramingRect == null) {
if (framingRect == null || previewSize == null) {
return;
}
final Rect frame = framingRect;
final Rect previewFrame = previewFramingRect;
final Size previewSize = this.previewSize;
final int width = canvas.getWidth();
final int height = canvas.getHeight();
final int width = getWidth();
final int height = getHeight();
// Draw the exterior (i.e. outside the framing rect) darkened
paint.setColor(resultBitmap != null ? resultColor : maskColor);
@@ -160,19 +162,19 @@ public class ViewfinderView extends View {
paint.setAlpha(CURRENT_POINT_OPACITY);
canvas.drawBitmap(resultBitmap, null, frame, paint);
} else {
// If wanted, draw a red "laser scanner" line through the middle to show decoding is active
if (laserVisibility) {
paint.setColor(laserColor);
// Draw a red "laser scanner" line through the middle to show decoding is active
paint.setColor(laserColor);
paint.setAlpha(SCANNER_ALPHA[scannerAlpha]);
scannerAlpha = (scannerAlpha + 1) % SCANNER_ALPHA.length;
final int middle = frame.height() / 2 + frame.top;
canvas.drawRect(frame.left + 2, middle - 1, frame.right - 1, middle + 2, paint);
paint.setAlpha(SCANNER_ALPHA[scannerAlpha]);
scannerAlpha = (scannerAlpha + 1) % SCANNER_ALPHA.length;
final float scaleX = frame.width() / (float) previewFrame.width();
final float scaleY = frame.height() / (float) previewFrame.height();
final int middle = frame.height() / 2 + frame.top;
canvas.drawRect(frame.left + 2, middle - 1, frame.right - 1, middle + 2, paint);
}
final int frameLeft = frame.left;
final int frameTop = frame.top;
final float scaleX = this.getWidth() / (float) previewSize.width;
final float scaleY = this.getHeight() / (float) previewSize.height;
// draw the last possible result points
if (!lastPossibleResultPoints.isEmpty()) {
@@ -181,8 +183,8 @@ public class ViewfinderView extends View {
float radius = POINT_SIZE / 2.0f;
for (final ResultPoint point : lastPossibleResultPoints) {
canvas.drawCircle(
frameLeft + (int) (point.getX() * scaleX),
frameTop + (int) (point.getY() * scaleY),
(int) (point.getX() * scaleX),
(int) (point.getY() * scaleY),
radius, paint
);
}
@@ -195,8 +197,8 @@ public class ViewfinderView extends View {
paint.setColor(resultPointColor);
for (final ResultPoint point : possibleResultPoints) {
canvas.drawCircle(
frameLeft + (int) (point.getX() * scaleX),
frameTop + (int) (point.getY() * scaleY),
(int) (point.getX() * scaleX),
(int) (point.getY() * scaleY),
POINT_SIZE, paint
);
}
@@ -246,4 +248,12 @@ public class ViewfinderView extends View {
if (possibleResultPoints.size() < MAX_RESULT_POINTS)
possibleResultPoints.add(point);
}
public void setMaskColor(int maskColor) {
this.maskColor = maskColor;
}
public void setLaserVisibility(boolean visible) {
this.laserVisibility = visible;
}
}
@@ -64,12 +64,9 @@ public final class AutoFocusManager {
private final Camera.AutoFocusCallback autoFocusCallback = new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera theCamera) {
handler.post(new Runnable() {
@Override
public void run() {
focusing = false;
autoFocusAgainLater();
}
handler.post(() -> {
focusing = false;
autoFocusAgainLater();
});
}
};
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.zxing.client.android.camera;
package com.journeyapps.barcodescanner.camera;
import android.annotation.TargetApi;
import android.graphics.Rect;
@@ -138,12 +138,7 @@ public class CameraInstance {
Util.validateMainThread();
if (open) {
cameraThread.enqueue(new Runnable() {
@Override
public void run() {
cameraManager.setTorch(on);
}
});
cameraThread.enqueue(() -> cameraManager.setTorch(on));
}
}
@@ -156,12 +151,7 @@ public class CameraInstance {
Util.validateMainThread();
if (open) {
cameraThread.enqueue(new Runnable() {
@Override
public void run() {
cameraManager.changeCameraParameters(callback);
}
});
cameraThread.enqueue(() -> cameraManager.changeCameraParameters(callback));
}
}
@@ -186,21 +176,13 @@ public class CameraInstance {
}
public void requestPreview(final PreviewCallback callback) {
mainHandler.post(new Runnable() {
@Override
public void run() {
if(!open) {
Log.d(TAG, "Camera is closed, not requesting preview");
return;
}
cameraThread.enqueue(new Runnable() {
@Override
public void run() {
cameraManager.requestPreviewFrame(callback);
}
});
mainHandler.post(() -> {
if (!open) {
Log.d(TAG, "Camera is closed, not requesting preview");
return;
}
cameraThread.enqueue(() -> cameraManager.requestPreviewFrame(callback));
});
}
@@ -24,7 +24,6 @@ import android.view.Surface;
import android.view.SurfaceHolder;
import com.google.zxing.client.android.AmbientLightManager;
import com.google.zxing.client.android.camera.CameraConfigurationUtils;
import com.google.zxing.client.android.camera.open.OpenCameraInterface;
import com.journeyapps.barcodescanner.Size;
import com.journeyapps.barcodescanner.SourceData;
@@ -97,11 +96,15 @@ public final class CameraManager {
PreviewCallback callback = this.callback;
if (cameraResolution != null && callback != null) {
try {
if(data == null) {
if (data == null) {
throw new NullPointerException("No preview data received");
}
int format = camera.getParameters().getPreviewFormat();
SourceData source = new SourceData(data, cameraResolution.width, cameraResolution.height, format, getCameraRotation());
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
source.setPreviewMirrored(true);
}
callback.onPreview(source);
} catch (RuntimeException e) {
// Could be:
@@ -112,7 +115,7 @@ public final class CameraManager {
}
} else {
Log.d(TAG, "Got preview callback, but no handler or resolution available");
if(callback != null) {
if (callback != null) {
// Should generally not happen
callback.onPreviewError(new Exception("No resolution available"));
}
@@ -153,7 +156,7 @@ public final class CameraManager {
* Must be called from camera thread.
*/
public void configure() {
if(camera == null) {
if (camera == null) {
throw new RuntimeException("Camera not open");
}
setParameters();
@@ -223,7 +226,7 @@ public final class CameraManager {
* @return true if the camera rotation is perpendicular to the current display rotation.
*/
public boolean isCameraRotated() {
if(rotationDegrees == -1) {
if (rotationDegrees == -1) {
throw new IllegalStateException("Rotation not calculated yet. Call configure() first.");
}
return rotationDegrees % 180 != 0;
@@ -277,11 +280,9 @@ public final class CameraManager {
}
if (settings.isMeteringEnabled()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
CameraConfigurationUtils.setVideoStabilization(parameters);
CameraConfigurationUtils.setFocusArea(parameters);
CameraConfigurationUtils.setMetering(parameters);
}
CameraConfigurationUtils.setVideoStabilization(parameters);
CameraConfigurationUtils.setFocusArea(parameters);
CameraConfigurationUtils.setMetering(parameters);
}
}
@@ -312,7 +313,7 @@ public final class CameraManager {
if (rawSupportedSizes == null) {
Camera.Size defaultSize = parameters.getPreviewSize();
if (defaultSize != null) {
// Work around potential platform bugs
Size previewSize = new Size(defaultSize.width, defaultSize.height);
previewSizes.add(new Size(defaultSize.width, defaultSize.height));
}
return previewSizes;
@@ -17,14 +17,14 @@ public class CameraSurface {
private SurfaceTexture surfaceTexture;
public CameraSurface(SurfaceHolder surfaceHolder) {
if(surfaceHolder == null) {
if (surfaceHolder == null) {
throw new IllegalArgumentException("surfaceHolder may not be null");
}
this.surfaceHolder = surfaceHolder;
}
public CameraSurface(SurfaceTexture surfaceTexture) {
if(surfaceTexture == null) {
if (surfaceTexture == null) {
throw new IllegalArgumentException("surfaceTexture may not be null");
}
this.surfaceTexture = surfaceTexture;
@@ -39,7 +39,7 @@ public class CameraSurface {
}
public void setPreview(Camera camera) throws IOException {
if(surfaceHolder != null) {
if (surfaceHolder != null) {
camera.setPreviewDisplay(surfaceHolder);
} else {
camera.setPreviewTexture(surfaceTexture);
@@ -27,7 +27,7 @@ public class CenterCropStrategy extends PreviewScalingStrategy {
*/
@Override
protected float getScore(Size size, Size desired) {
if(size.width <= 0 || size.height <= 0) {
if (size.width <= 0 || size.height <= 0) {
return 0f;
}
Size scaled = size.scaleCrop(desired);
@@ -36,7 +36,7 @@ public class CenterCropStrategy extends PreviewScalingStrategy {
// Treat downscaling as slightly better than upscaling
float scaleScore;
if(scaleRatio > 1.0f) {
if (scaleRatio > 1.0f) {
// Upscaling
scaleScore = (float)Math.pow(1.0f / scaleRatio, 1.1);
} else {
@@ -27,7 +27,7 @@ public class FitCenterStrategy extends PreviewScalingStrategy {
*/
@Override
protected float getScore(Size size, Size desired) {
if(size.width <= 0 || size.height <= 0) {
if (size.width <= 0 || size.height <= 0) {
return 0f;
}
Size scaled = size.scaleFit(desired);
@@ -36,7 +36,7 @@ public class FitCenterStrategy extends PreviewScalingStrategy {
// Treat downscaling as slightly better than upscaling
float scaleScore;
if(scaleRatio > 1.0f) {
if (scaleRatio > 1.0f) {
// Upscaling
scaleScore = (float)Math.pow(1.0f / scaleRatio, 1.1);
} else {
@@ -12,7 +12,7 @@ public class FitXYStrategy extends PreviewScalingStrategy {
private static float absRatio(float ratio) {
if(ratio < 1.0f) {
if (ratio < 1.0f) {
return 1.0f / ratio;
} else {
return ratio;
@@ -33,7 +33,7 @@ public class FitXYStrategy extends PreviewScalingStrategy {
*/
@Override
protected float getScore(Size size, Size desired) {
if(size.width <= 0 || size.height <= 0) {
if (size.width <= 0 || size.height <= 0) {
return 0f;
}
float scaleX = absRatio(size.width * 1.0f / desired.width);