Compare commits

..
9 Commits
Author SHA1 Message Date
Markus Fisch 694c854650 Advance version number to 1.68.1 2026-02-21 21:50:51 +01:00
Markus Fisch b1cd12ec77 Validate frame data before giving it to ZXing
And refactor preview callback to use an early exit for clarity.

According to Vitals, `frameData` can apparently be `null` on
some devices sometimes.
2026-02-21 21:40:38 +01:00
Markus Fisch 0c27b15025 Check if fragment is still added
Before setting brightness, which may happen later because
it's called from the queue.
2026-02-21 21:20:31 +01:00
Markus Fisch 5de950bdbf Update tools version 2026-02-21 19:14:54 +01:00
Markus Fisch ae9e304ef6 Handle bad decoded intent parcelables safely
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.
2026-02-21 19:13:47 +01:00
Dominik StadlerandMarkus Fisch c4cc14554b Clear search-term on empty input, not on "Cancel"
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.
2026-02-20 13:52:50 +01:00
Dominik StadlerandMarkus Fisch d6afccf562 Apply some IDE suggestions 2026-02-20 13:52:50 +01:00
Markus Fisch a90bdad117 Update ZXingCpp
And remove the now missing `returnCodabarStartEnd` feature.
2026-02-13 19:05:35 +01:00
solokotandGitHub 52d4f082f2 Update Russian translation
Small Improvements
2026-02-12 19:45:38 +01:00
9 changed files with 89 additions and 69 deletions
+6
View File
@@ -1,5 +1,11 @@
# Change Log
## 1.68.1
* Improve UI of search barcode dialog
* Stability improvements
* Update ZXingCpp
* Update Russian translation
## 1.68.0
* Add automated actions
* Improve managing profiles
+3 -3
View File
@@ -8,8 +8,8 @@ android {
minSdk 9
targetSdk sdk_version
versionCode 154
versionName '1.68.0'
versionCode 155
versionName '1.68.1'
}
signingConfigs {
@@ -78,7 +78,7 @@ dependencies {
// External
implementation 'com.github.markusfisch:CameraView:1.10.0'
implementation 'com.github.markusfisch:ScalingImageView:1.4.1'
implementation 'com.github.markusfisch:zxing-cpp:v2.3.0.4'
implementation 'com.github.markusfisch:zxing-cpp:v3.0.1.0'
// Testing
testImplementation 'junit:junit:4.13.2'
@@ -268,7 +268,7 @@ class CameraActivity : AppCompatActivity() {
super.onPause()
closeCamera()
if (shouldStoreSettings) {
storeSettings();
storeSettings()
}
shouldStoreSettings = true
}
@@ -432,14 +432,14 @@ class CameraActivity : AppCompatActivity() {
val term = editText.text.toString().trim()
if (!term.isEmpty()) {
searchTerm = term.toRegex()
ignoreNext = null
} else {
searchTerm = null
}
ignoreNext = null
updateTitle()
}
.setNegativeButton(android.R.string.cancel) { _, _ ->
searchTerm = null
ignoreNext = null
updateTitle()
// do not change anything on cancel
}
.show()
}
@@ -604,50 +604,53 @@ class CameraActivity : AppCompatActivity() {
tryRotate = prefs.autoRotate,
tryInvert = true,
tryDownscale = true,
returnCodabarStartEnd = true,
maxNumberOfSymbols = 1,
textMode = TextMode.PLAIN
)
var useLocalAverage = false
camera.setPreviewCallback { frameData, _ ->
if (decoding) {
useLocalAverage = useLocalAverage xor true
ZxingCpp.readByteArray(
frameData,
frameMetrics.width,
frameRoi.left, frameRoi.top,
frameRoi.width(), frameRoi.height(),
frameMetrics.orientation,
options.apply {
// By default, ZXing uses LOCAL_AVERAGE, but
// this does not work well with inverted
// barcodes on low-contrast backgrounds.
binarizer = if (useLocalAverage) {
Binarizer.LOCAL_AVERAGE
} else {
Binarizer.GLOBAL_HISTOGRAM
}
formats = formatsToRead
if (!decoding ||
frameData == null ||
frameData.isEmpty()
) {
return@setPreviewCallback
}
useLocalAverage = useLocalAverage xor true
ZxingCpp.readByteArray(
frameData,
frameMetrics.width,
frameRoi.left, frameRoi.top,
frameRoi.width(), frameRoi.height(),
frameMetrics.orientation,
options.apply {
// By default, ZXing uses LOCAL_AVERAGE, but
// this does not work well with inverted
// barcodes on low-contrast backgrounds.
binarizer = if (useLocalAverage) {
Binarizer.LOCAL_AVERAGE
} else {
Binarizer.GLOBAL_HISTOGRAM
}
)?.let { results ->
val result = results.first()
val text = result.text
if (text == ignoreNext) {
return@let
}
val term = searchTerm
if (term != null &&
!text.matches(term) &&
!text.contains(term)
) {
ignoreNext = text
errorFeedback()
toast(R.string.does_not_match_search_term)
return@let
}
postResult(result)
decoding = false
formats = formatsToRead
}
)?.let { results ->
val result = results.first()
val text = result.text
if (text == ignoreNext) {
return@let
}
val term = searchTerm
if (term != null &&
!text.matches(term) &&
!text.contains(term)
) {
ignoreNext = text
errorFeedback()
toast(R.string.does_not_match_search_term)
return@let
}
postResult(result)
decoding = false
}
}
}
@@ -785,7 +788,7 @@ class CameraActivity : AppCompatActivity() {
}
when {
returnResult -> {
setResult(Activity.RESULT_OK, getReturnIntent(result))
setResult(RESULT_OK, getReturnIntent(result))
finish()
}
@@ -148,11 +148,15 @@ class MainActivity : AppCompatActivity() {
}
}
private fun Intent.getScanExtra(name: String): Scan? = if (
Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU
) {
@Suppress("DEPRECATION")
getParcelableExtra(name)
} else {
getParcelableExtra(name, Scan::class.java)
private fun Intent.getScanExtra(name: String): Scan? = try {
if (
Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU
) {
@Suppress("DEPRECATION")
getParcelableExtra(name)
} else {
getParcelableExtra(name, Scan::class.java)
}
} catch (_: Throwable) {
null
}
@@ -49,7 +49,6 @@ class PickActivity : AppCompatActivity() {
tryRotate = true,
tryInvert = true,
tryDownscale = true,
returnCodabarStartEnd = true,
maxNumberOfSymbols = 1,
formats = prefs.barcodeFormats.toFormatSet()
)
@@ -450,6 +450,9 @@ class BarcodeFragment : Fragment() {
private fun brightenScreen() {
activity?.let {
if (!isAdded) {
return
}
currentBrightness = it.getScreenBrightness()
it.setScreenBrightness(1f)
brightenScreenItem.isChecked = true
@@ -457,7 +460,7 @@ class BarcodeFragment : Fragment() {
}
private fun restoreScreenBrightness() {
if (currentBrightness > -1f) {
if (currentBrightness > -1f && isAdded) {
activity?.setScreenBrightness(currentBrightness)
currentBrightness = -1f
brightenScreenItem.isChecked = false
+13 -13
View File
@@ -42,11 +42,11 @@
<string name="error_flash">Ошибка при переключении вспышки</string>
<string name="share">Поделиться</string>
<string name="share_file">Поделиться файлом</string>
<string name="share_as">Поделиться как?</string>
<string name="copy_to_clipboard">Скопировать в буфер обмена</string>
<string name="copy_as_deeplink">Копировать как диплинк</string>
<string name="share_as">Поделиться</string>
<string name="copy_to_clipboard">Копировать в буфер обмена</string>
<string name="copy_as_deeplink">Копировать как прямую ссылку</string>
<string name="copied_to_clipboard">Скопировано в буфер обмена</string>
<string name="copy_password">Скопировать пароль в буфер обмена</string>
<string name="copy_password">Копировать пароль в буфер обмена</string>
<string name="open_url">Открыть URL</string>
<string name="cannot_resolve_action">Не найдено приложение для этого действия</string>
<string name="pick_search_engine">Выберите поисковую систему</string>
@@ -143,7 +143,7 @@
<string name="automated_actions">Автоматические действия</string>
<string name="automated_actions_none">Нет автоматических действий</string>
<string name="automated_actions_empty">Пока нет автоматических действий</string>
<string name="automated_actions_empty">Автоматических действий пока нет</string>
<plurals name="automated_actions_count">
<item quantity="one">%d автоматическое действие</item>
<item quantity="few">%d автоматических действия</item>
@@ -151,9 +151,9 @@
<item quantity="other">%d автоматических действий</item>
</plurals>
<string name="automated_action_add">Добавить действие</string>
<string name="automated_action_edit">Редактировать действие</string>
<string name="automated_action_edit">Изменить действие</string>
<string name="automated_action_regex">Регулярное выражение</string>
<string name="automated_action_regex_hint">напр. ^https?://.*</string>
<string name="automated_action_regex_hint">например: ^https?://.*</string>
<string name="automated_action_regex_required">Требуется регулярное выражение</string>
<string name="automated_action_regex_invalid">Неверное регулярное выражение</string>
<string name="automated_action_type">Тип действия</string>
@@ -202,10 +202,10 @@
<string name="enter_name">Укажите название сканирования</string>
<string name="enter_name_hint">Название сканирования</string>
<string name="no_barcode_found">Штрих-код не найден</string>
<string name="pick_list_separator">Как разделять пункты списка?</string>
<string name="pick_list_separator">Разделение элементов списка</string>
<string name="separator_line_break">Разрыв строки</string>
<string name="separator_ruler">Горизонтальная линия</string>
<string name="save_as_file_name">Сохранить в папке скачиваний Downloads?</string>
<string name="save_as_file_name">Сохранить в файл с именем</string>
<string name="file_name">Имя файла</string>
<string name="error_saving_file">Невозможно сохранить файл</string>
<string name="error_file_exists">Файл уже существует</string>
@@ -228,12 +228,12 @@
<string name="add_to_history">Добавить в историю</string>
<string name="added_to_history">Добавлено в историю</string>
<string name="export_to_file">Экспортировать в файл</string>
<string name="export_as">Экспортировать как?</string>
<string name="export_as">Формат файла экспорта</string>
<string name="export_csv_comma">CSV (разделитель – запятая)</string>
<string name="export_csv_semicolon">CSV (разделитель – точка с запятой)</string>
<string name="export_json">JSON</string>
<string name="export_database">База данных SQLite</string>
<string name="saved_in_downloads">Сохранено в загрузках</string>
<string name="saved_in_downloads">Сохранено в папке Downloads</string>
<string name="rotate_image_cw">Повернуть изображение по часовой стрелке</string>
<string name="toggle_free_rotation">Переключить свободный поворот</string>
<string name="pick_file">Открыть файл</string>
@@ -260,12 +260,12 @@
<string name="email_subject">Тема</string>
<string name="email_body">Текст</string>
<string name="scheme">Схема</string>
<string name="host">Хост</string>
<string name="host">Узел</string>
<string name="query">Запрос</string>
<string name="automated_action_type_custom_intent">Пользовательский Intent</string>
<string name="automated_action_intent_uri_template">Шаблон URI Intent</string>
<string name="automated_action_intent_uri_hint">intent:#Intent;action=android.intent.action.SEND;type=text/plain;S.android.intent.extra.TEXT={RESULT};end</string>
<string name="automated_action_intent_uri_required">URI Intent обязателен</string>
<string name="automated_action_intent_uri_required">Требуется URI Intent</string>
<string name="automated_action_intent_uri_invalid">Недопустимый URI Intent</string>
<string name="automated_action_list_custom_intent">Пользовательский Intent: %s</string>
<string name="automated_action_list_custom_intent_empty">Пользовательский Intent</string>
+1 -1
View File
@@ -1,7 +1,7 @@
buildscript {
ext {
kotlin_version = '2.2.21'
tools_version = '9.0.0'
tools_version = '9.0.1'
sdk_version = 36
support_version = '25.3.1'
}
@@ -0,0 +1,5 @@
* Improve UI of search barcode dialog
* Stability improvements
* Update ZXingCpp
* Update Russian translation