Older history entries can miss the stored symbol matrix and
therefore fall back to re-encoding the barcode content.
After the ZXingCpp 3 migration, that fallback used a zero margin,
so recreated barcodes from those records lost their quiet zone.
And remove lateinit from `brightenScreenItem` to check
if it's null or not.
Also delay automatic brightening to give Android a bit
more time to sort things out.
Linear zoom 0 switches to the ultra-wide lens on devices
that support it, causing blurry images. Mapping to zoom ratios
from 1.0x to maxZoomRatio keeps the main lens in use.
Because the previous zoom levels were for the legacy camera API
and they don't carry over to CameraX.
With CameraX, it's also better to start with no zoom.
Which greatly improves the initial sharpness of the camera image.
Without this, despite autofocus, the initial camera frame can be
a bit blurry on some devices.
CameraX defaults to CONTINUOUS_VIDEO autofocus, which trades
focus accuracy for smooth transitions. For barcode scanning we
need the sharpest possible lock, so switch to CONTINUOUS_PICTURE.
But this still isn't enough to have the same quick autofocus the
legacy API had.
To configure the camera for barcode reading (macro focus range,
disabled stabilisation). Same way the legacy Camera API's
SCENE_MODE_BARCODE did.
Unfortunately, this mode isn't supported by some camera drivers
and it doesn't really improve focusing near barcodes on my test
devices.
Replace legacy support dependencies and namespaces with AndroidX and
Material equivalents so the app builds on the modern stack again.
Update Kotlin imports, XML widget class names, and manifest provider
references, then fix AndroidX nullability fallout and missing lifecycle
super calls reported by lint.
Remove MainActivity as a single fragment host and convert each
fragment (Barcode, Decode, Encode, History, Profiles, Automated
Actions, Network Suggestions) into its own Activity.
Update CameraActivity to launch each Activity directly instead of
routing through MainActivity intent factories.
Stop transporting Scan as a Parcelable and keep only the
bundle-based handoff for decoded results.
This removes version-sensitive parcel decoding entirely and makes
scan navigation stable across app updates.
Replace Scan parcelables in the decode navigation flow with plain
Bundle data.
This avoids BadParcelableException when Android lazily unparcels a
Scan written with a different layout or legacy ZXingCpp format names.
A bundle of primitives is stable across app updates and does not depend
on custom parcel compatibility.
Which is required (to build and run) version 3 of ZXingCpp,
because ZXingCpp requires C++20, which in turn requires an
NDK with minSdk 21.
So to use the new version, we need to raise the minSdk
and cut off old devices just because C++17 didn't cut the
mustard anymore. Well, I guess this had to happen at some
point, and because SDK 21 is 12 years old now, it's probably
even reasonable to raise the bar.
Because 3.x requires C++20, what requires minSdk 21.
While ZXingC++ 3.x compiles and runs on some devices (with the
current minSdk), the library does crash on other devices.
So updating to ZXingC++ 3.x requires more work, unfortunately.
This reverts commit
a90bdad1174b2eb806127a59126312
Since ZXingCpp v3.0.0+ changed the default from -1 to 0.
Using -1 results in an exception in `BitMatrix::setRegion()`
because of invalid top/left coordinates.
When getting the DECODE extra.
`getParcelableExtra(name, Class)` can throw on some versions
of Android when the ClassLoader associated with the Bundle's
lazy-decoded value is null in certain scenarios (e.g., after
an activity restart where the system re-delivers the intent).
Simply fallback to the "deprecated" `getParcelableExtra(name)`
which works in this case, because it doesn't verify the
parcelable's class against Scan::class.java.
Since ZXingCpp v3.0.0+ changed the default from -1 to 0.
Using -1 results in an exception in `BitMatrix::setRegion()`
because of invalid top/left coordinates.
Guard reading the `decoded` Scan extra in MainActivity against
framework unparcel exceptions. Some external or malformed intents can
trigger a NullPointerException in Parcel before app-level checks run.
Return null when unparceling fails so the app falls back to the default
DecodeFragment path instead of crashing on launch.
Clearing search-term on cancel and not on empty input is
unexpected. "Cancel" usually does not change the state.
Rather clear the searchTerm on empty input and do not
handle the "Cancel"-button at all.