L×Box v2.20.0
Two things you can now do that you couldn't before: import a config by
scanning a QR code with the camera, and save a backup as a file instead of
only sending it through the share sheet. The app no longer freezes with
"isn't responding" while reloading a large config. And the diagnostic report
you send us is now readable and says which build it came from.
Два новых действия: импорт конфига сканированием QR-кода камерой и сохранение "Scan QR code" in the ⋮ menu on the servers screen used to answer with "QR QR is how most providers hand out configs — a code on the panel page, a Whatever the code contains goes through the same import as a paste: a single Nodes added this way are marked with source The APK grew by 3.8 MB — that's the ML Kit barcode scanner and CameraX.
Export now asks how you want it:
This came from a user report: "on some devices without a third-party file Options your device can't do aren't shown.
Applying a config change to a running tunnel could freeze the interface for Reloading rebuilds the whole core instance — parsing the config and The reload now runs off the UI thread, so the interface stays responsive Two neighbouring actions went the same way, for the same reason: clearing This was not a core problem — the core was doing its normal work, it was When a subscription points nodes at a relay that isn't currently built — a In one user's dump that came to 276 lines out of 305. Everything else had It's now one line per missing relay: how many nodes referenced it, the names Before this, the core version reached the report only by accident — as a Nothing changes for you: updates install as before. This is about how builds Android orders updates by an integer The number is now derived from the version itself: Your installed build carries a much smaller number (3606 on arm64), so the 2941 tests green, analyzer clean, all four localization checkers at zero.
QR scanning and backup export are both device-verified (04.08.2026): a phone The version-code change is device-verified (05.08.2026, arm64 emulator on The freeze fix has not been verified on a device: reproducing it needs a Пункт «Scan QR code» в меню ⋮ на экране серверов раньше отвечал «QR scanner QR — основной способ раздачи конфигов: код на странице панели, скриншот в Содержимое кода уходит в тот же разбор, что и вставка из буфера: работает и Узлы, добавленные сканером, помечаются источником APK вырос на 3.8 МБ — это сканер штрихкодов ML Kit и CameraX.
Экспорт теперь спрашивает способ:
Пришло из жалобы: «бэкап на некоторых устройствах без стороннего файлового Способы, недоступные на конкретном устройстве, в списке не показываются.
Применение изменений конфига к работающему туннелю могло заморозить Перезагрузка пересобирает весь инстанс ядра — разбирает конфиг и заново Теперь перезагрузка идёт вне потока интерфейса, и он остаётся отзывчивым при Тем же путём отправились два соседних действия по той же причине: сброс Проблема была не в ядре — ядро делало свою обычную работу, его просто звали Когда подписка направляет узлы через посредника, которого сейчас в конфиге В дампе одного из пользователей это дало 276 строк из 305. Всё остальное из Теперь строка одна на каждого недостающего посредника: сколько узлов на него Раньше версия ядра попадала в отчёт случайно — полем внутри снимков крашей Для вас ничего не меняется: обновления ставятся как раньше. Речь о том, как Android упорядочивает обновления по целому числу Теперь число выводится из самой версии: У установленной у вас сборки число намного меньше (3606 для arm64), новая 2941 тест зелёный, анализатор чист, все четыре чекера локализации по нулям.
Сканирование QR и экспорт бэкапа проверены на устройствах (04.08.2026): Смена схемы versionCode проверена на устройстве (05.08.2026, эмулятор arm64 Исправление зависания на устройстве не проверено: для воспроизведения нужна
бэкапа файлом, а не только через «поделиться». Приложение больше не зависает
с «не отвечает» при перезагрузке большого конфига. А диагностический отчёт,
который вы нам присылаете, стал читаемым и теперь сообщает, на какой сборке
снят.
🇬🇧 English
📷 Added — import by scanning a QR code
scanner coming soon". It now opens the camera.
screenshot in a support chat. Until now you had to decode it with another
app and paste the result.
proxy link or a subscription URL, both work. Before anything is added you
get a confirmation dialog showing what actually arrived — a QR code is
untrusted input, and nothing is imported silently.
qr. Devices without a camera
(Android TV) don't show the menu item at all: unlike file import, where the
clipboard and a URL remain as alternatives, scanning has no fallback.
💾 Added — backup export can save a file
(Android 10+).
manager there's no way to save the backup". Export only ever opened the
share sheet, and the file itself lived in the app cache — where it went was
whatever you picked in the sheet, and the cache gets cleared eventually. With
no file manager installed there was often no "save to files" target in the
sheet at all.
💥 Fixed — the app froze with "isn't responding" while reloading the config
long enough that Android offered to close the app. The fix came from a user
report with a diagnostic dump.
assembling every outbound, DNS and routing. That work was running on the UI
thread, so nothing was drawn and no taps were handled until it finished. On
a typical config it takes a fraction of a second and passes unnoticed; on a
subscription with several hundred nodes it went past the five-second mark
where Android declares the app unresponsive.
regardless of how large the config is. The tunnel still drops and comes back
during a reload, as before.
the DNS cache (it reloads too) and the network reset.
simply being called from the wrong thread.
🔎 Fixed — the diagnostic report drowned in its own noise
disabled WARP preset is the usual case — the app drops the broken link and
warns about it. It used to warn once per node: 138 nodes meant 138 identical
lines per rebuild.
been pushed out of the log, including the events we needed to read.
of the first five, and a count of the rest.
🏷 Fixed — the diagnostic report now says which build it came from
Share dump writes app_version, app_build and core_version at the top
of the file.
field inside crash or OOM snapshots, because the core puts it there itself.
No snapshots, no version. The app's own version was never in the report at
all. First question on any report is which build to reproduce on, and the
report couldn't answer it.
🔧 Process — the version code is derived from the version
are numbered.
versionCode. Until now ours was the
number of commits in history — a value that says how often someone committed,
not which version this is. That made the version impossible to read from the
sources, which is what F-Droid's update checker does. Automatic updates in
their catalogue were therefore off, and every version needed a manual merge
request.
2.20.0 on arm64 becomes
22000502, where the digits carry major, minor, patch, the stage
(release candidate, release, hotfix) and the architecture. The architecture
is the last digit on purpose — F-Droid sorts by this number, and with the
architecture in the leading digits an old x86_64 build outranks a new armv7
one, scrambling the version list.
new scheme is far above it and updates keep working. Verified on a device.
✅ Tests
emulator on API 34 and an Android TV emulator on API 31. The version fields
are device-verified too (05.08.2026, on a phone). The aggregated warning has
four tests of its own.
Android 14): a build carrying the old number installs over with the new one
without uninstalling, and an equal number still installs — the property local
dev builds depend on.
subscription of several hundred nodes, since a normal config never reaches
the freeze threshold. Kotlin compiles clean.
🇷🇺 Русский
📷 Добавлено — импорт сканированием QR-кода
coming soon». Теперь он открывает камеру.
чате поддержки. До сих пор его приходилось распознавать сторонним
приложением и вставлять результат вручную.
одиночная proxy-ссылка, и ссылка на подписку. Перед добавлением показывается
диалог подтверждения с тем, что реально приехало в коде — QR недоверенный
ввод, молча ничего не добавляется.
qr. На устройствах без
камеры (Android TV) пункт меню не показывается вовсе: в отличие от импорта
файла, где остаются буфер обмена и ссылка, у сканирования замены нет.
💾 Добавлено — экспорт бэкапа умеет сохранять файл
(Android 10+).
менеджера не сохранить». Экспорт открывал только share-sheet, а сам файл
лежал в кэше приложения — куда он попадёт, решал выбор в шите, а кэш рано
или поздно вычищается системой. Без файлового менеджера пункта «сохранить в
файлы» в шите часто не было вообще.
💥 Исправлено — приложение зависало с «не отвечает» при перезагрузке конфига
интерфейс настолько, что Android предлагал закрыть приложение. Исправление
пришло из жалобы пользователя вместе с диагностическим дампом.
строит все узлы, DNS и маршрутизацию. Эта работа шла на потоке интерфейса,
поэтому до её завершения ничего не отрисовывалось и нажатия не
обрабатывались. На обычном конфиге она занимает доли секунды и проходит
незаметно; на подписке в несколько сотен узлов выходила за пять секунд —
порог, после которого Android считает приложение зависшим.
любом размере конфига. Туннель во время перезагрузки по-прежнему отваливается
и поднимается заново — это не изменилось.
DNS-кэша (он тоже делает перезагрузку) и сброс сети.
не с того потока.
🔎 Исправлено — диагностический отчёт тонул в собственном шуме
нет (типовой случай — выключенный WARP-пресет), приложение снимает битую
ссылку и предупреждает об этом. Предупреждение писалось на каждый узел: 138
узлов давали 138 одинаковых строк за одну пересборку.
лога вытеснилось, включая события, которые и надо было прочитать.
ссылались, имена первых пяти и счётчик остальных.
🏷 Исправлено — по отчёту видно, на какой сборке он снят
Share dump пишет в начало файла app_version, app_build и
core_version.
или OOM, потому что их кладёт туда само ядро. Нет снимков — нет и версии.
Версии самого приложения в отчёте не было никогда. При этом первый вопрос по
любому отчёту — на какой сборке воспроизводить, и ответить на него отчёт не
мог.
🔧 Процесс — код версии выводится из самой версии
нумеруются сборки.
versionCode. До сих пор им
было число коммитов в истории — величина, которая говорит, сколько раз
кто-то закоммитил, а не какая это версия. Из-за этого версию нельзя было
прочитать из исходников, а именно так её ищет F-Droid. Автообновление в их
каталоге поэтому было выключено, и каждая версия требовала ручного
merge request.
2.20.0 для arm64 даёт 22000502,
где разряды несут major, minor, patch, стадию (кандидат, релиз, заплатка) и
архитектуру. Архитектура стоит последней цифрой намеренно — F-Droid
сортирует по этому числу, и когда архитектура попадает в старшие разряды,
старая сборка под x86_64 оказывается «новее» новой под armv7, а список версий
едет вперемешку.
схема заведомо выше — обновления продолжают работать. Проверено на
устройстве.
✅ Тесты
эмулятор телефона API 34 и эмулятор Android TV API 31. Поля с версиями тоже
проверены на устройстве (05.08.2026, телефон). У агрегированного
предупреждения — четыре собственных теста.
на Android 14): сборка со старым числом обновляется на новое без удаления, а
равное число по-прежнему ставится — на это свойство опираются локальные
dev-сборки.
подписка в несколько сотен узлов, обычный конфиг до порога зависания не
доходит. Kotlin компилируется чисто.
📲 Install
adb install -r LxBox-v2.20.0-arm64-v8a.apkБез uninstall! Поверх существующей установки. Настройки и подписки сохранятся.
No uninstall needed — install over the existing one. Settings and
subscriptions are preserved.
Previous release / Предыдущий релиз: v2.19.7.