APRS RadioRubka
Android-приложение: анимированная заставка «APRS» → веб-карта APRS и пуш-уведомления (RuStore Push). Кнопка «назад» закрывает приложение, экран не гаснет при активном приложении.
- Пакет:
ru.ua1zbe.aprsmap - Карта: https://aprs.radiorubka.org/?center=67.5096,32.8271&zoom=8
(задаётся строкой
map_urlвapp/src/main/res/values/strings.xml) - Репозиторий: https://git2.ua1zbe.ru/ua1zbe/aprsmap
Стек сборки
- Gradle wrapper 9.2.0, AGP 8.13.2, Kotlin 2.2.21, JDK 25
- compileSdk 34, targetSdk 34, minSdk 26
Не использовать системный gradle 4.4.1 — только
./gradlew.
Сборка
./gradlew :app:assembleDebug # отладочный APK
./gradlew :app:assembleRelease # релизный APK (подписан)
Релизный APK: app/build/outputs/apk/release/app-release.apk.
Перед релизной сборкой нужны (в git НЕ хранятся):
keystore.properties— подпись релиза (файл в корне проекта):storeFile=/полный/путь/aprsmap-release.jks storePassword=... keyAlias=aprsmap keyPassword=...aprsmap-release.jks— файл ключа (.gitignore).
Отпечаток подписи (SHA-256) релиза. Получение:
keytool -list -v -keystore aprsmap-release.jks -alias aprsmap -storepass <пароль> | grep SHA256
# или
$ANDROID_HOME/build-tools/35.0.0/apksigner verify --print-certs app-release.apk
Версионирование
app/build.gradle.kts:
versionCode = 4 // инкремент для каждого релиза
versionName = "1.0.3"
Установка на телефон (adb)
$ANDROID_HOME/platform-tools/adb install -r app/build/outputs/apk/release/app-release.apk
$ANDROID_HOME/platform-tools/adb shell am start -n ru.ua1zbe.aprsmap/.SplashActivity
Запуск только через .SplashActivity (MainActivity не exported).
Google Play Protect может блокировать sideload — выключите усиленную защиту.
Выпуск релиза на Gitea
- Собрать
assembleRelease. - Токен API Gitea — в
/tmp/gitea_token.txt(Authorization: token). - Создать релиз и загрузить APK (см. пример ниже). Имена тегов:
v1.0.0,v1.0.1, ...
TOKEN=$(cat /tmp/gitea_token.txt)
curl -s -X POST -H "Authorization: token $TOKEN" -H "Content-Type: application/json" \
-d '{"tag_name":"v1.0.3","target_commitish":"main","name":"v1.0.3","body":"...","draft":false,"prerelease":false}' \
"https://git2.ua1zbe.ru/api/v1/repos/ua1zbe/aprsmap/releases"
# затем прикрепить APK, взяв id релиза:
curl -s -H "Authorization: token $TOKEN" \
-F "attachment=@app/build/outputs/apk/release/app-release.apk" \
"https://git2.ua1zbe.ru/api/v1/repos/ua1zbe/aprsmap/releases/<id>/assets?name=APRS_RadioRubka_v1.0.3.apk"
Сверка обновлений идёт по интерфейсу
https://git2.ua1zbe.ru/api/v1/repos/ua1zbe/aprsmap/releases/latest
— поэтому репозиторий публичный.
Автообновление
- При старте
MainActivity.checkForUpdates()сравниваетversionNameс последним релизом Gitea; если есть новее — диалог «Обновить». - APK скачивается в
cacheDir/updates/, установка черезContentProviderUpdateFileProvider(authorityru.ua1zbe.aprsmap.fileprovider)ACTION_VIEW, при необходимости запрос «Разрешить установку из этого источника».
tools/push.sh— служебное, рассылка пушей (см. ниже).
Пуш-уведомления (RuStore Push)
Актуально с v1.0.3. SDK ru.rustore.sdk:pushclient:7.4.0, топик рассылки —
aprsmap.
- Параметры в
app/src/main/java/ru/ua1zbe/aprsmap/App.kt:RUSTORE_PROJECT_ID(project id из консоли RuStore),PUSH_TOPIC. При старте:RuStorePushClient.init→getToken→subscribeToTopic("aprsmap"). PushMessagingServiceполучаетonNewToken/onMessageReceived; уведомления с секциейnotificationпоказывает сам SDK,dataс ключамиtitle/body— приложение. Каналaprs_push.- Токен устройства пишется в
shared_prefs/aprsmap.xml(push_token) и виден в logcatRuStorePush:.
Секреты (в git НЕ хранить)
tools/.push.secrets (в .gitignore):
SERVICE_TOKEN="..."
PROJECT_ID="..."
SDK на устройстве требует установленный и авторизованный RuStore.
Рассылка всем подписчикам топика
./tools/push.sh "Заголовок" "Текст"
Реализация: POST https://vkpns-topics.rustore.ru/v1/projects/{PROJECT_ID}/topics/aprsmap/publish
с Authorization: Bearer {SERVICE_TOKEN}. Ответ
{"message":"payload has been successfully published to topic aprsmap"} — успех.
Точечная отправка на устройство
curl -s -X POST \
"https://vkpns.rustore.ru/v1/projects/${PROJECT_ID}/messages:send" \
-H "Authorization: Bearer ${SERVICE_TOKEN}" -H "Content-Type: application/json" \
-d '{"message":{"token":"<push_token устройства>","notification":{"title":"...","body":"..."}}}'
Проверка на устройстве
adb logcat -d | grep -E "RuStorePush:"
adb shell dumpsys notification | grep -E "aprs_push|aprsmap"
Ожидаемое: push token: ..., subscribed to aprsmap, push displayed by SDK.