Неофициальный мобильный клиент для svalko.org.
Скопируй secrets.json.example → secrets.json и заполни значения:
{
"APP_SECRET": "...",
"CRASH_HANDLER_URL": "https://your-worker.workers.dev"
}secrets.json не коммитится. Без него приложение работает, но краш-репортер отключён.
make run # flutter run с подстановкой секретов
make bundle # flutter build appbundle (Google Play)
make apk # flutter build apk (предложит выбрать ABI)Версия берётся из последнего git-тега: git tag 1.2.7 && make bundle.
- AAB:
build/app/outputs/bundle/release/app-release.aab - APK:
build/app/outputs/flutter-apk/app-release.apk
Создайте android/key.properties (не коммитить):
storePassword=...
keyPassword=...
keyAlias=svalko
storeFile=svalko.keystoreKeystore генерируется один раз:
keytool -genkey -v \
-keystore android/app/svalko.keystore \
-alias svalko \
-keyalg RSA -keysize 2048 -validity 10000При необработанном исключении приложение отправляет POST на CRASH_HANDLER_URL.
Заголовок:
X-App-Secret: <APP_SECRET>
Content-Type: application/json
Тело:
{
"error": "StateError: bad state",
"stack": "#0 ...\n#1 ...",
"version": "1.2.7+312",
"device": "Google Pixel 7, Android 14",
"fatal": false,
"breadcrumbs": [...]
}stack — первые 12 непустых строк стектрейса. Повторная отправка одной и той же ошибки дедуплицируется (отправляется только один раз подряд).
fatal: true — ошибка поймана в PlatformDispatcher.onError или runZonedGuarded; без обработчика приложение бы упало. fatal: false — ошибка поймана в FlutterError.onError или блоке try/catch; приложение продолжало работать.
Вместе с ошибкой отправляются последние 30 действий пользователя (breadcrumbs): навигация между экранами и HTTP-запросы.