Files
BusSchedule127/README.md

143 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Автобус №127 — Расписание (Android)
Приложение с расписанием автобуса **№127** по маршруту
**Кандалакша — Полярные Зори — Зашеек** (Мурманская область).
## Возможности
- **Выбор остановки** — Кандалакша / Полярные Зори / Зашеек. При выборе
показываются доступные направления (куда можно уехать).
- **Ближайшие рейсы** — по 3 на каждое направление, с подсчётом
«через N ч M мин» (время по **МСК**, обновляется каждые 30 сек).
- **Автоопределение дня недели** — будни/выходные.
- **Полное расписание** — по кнопке раскрывается вся таблица
(4 остановки: Кандалакша · ПЗ→Зашеек · Зашеек · ПЗ→Кандалакша).
- **Карта с автобусами** — пункт меню «Карта» открывает VK Карты: видно
пройденный участок маршрута и автобусы прямо сейчас (без подписей остановок —
они были бы только шумом). Положение считается **по расписанию** (приложение
не берёт координаты с GPS), поэтому это оценка с точностью до нескольких
минут; внизу перечислены автобусы с направлением и временем прибытия.
Обновление каждые 20 сек.
- **Пуш-уведомления** — через RuStore Push, см. раздел ниже.
- **Меню** — кнопка `⋮` в шапке открывает выпадающее окошко с пунктами
«Карта» и «О приложении». Меню сворачивается после выбора пункта, по нажатию
вне его и по кнопке «‹» (которая в этом случае только закрывает меню,
а не уходит назад).
- Тёмная тема, живые часы МСК, подсветка ближайших рейсов (< 15 мин).
## Технические данные
| Параметр | Значение |
|-----------------|------------------------------|
| Тип | WebView-обёртка (HTML/JS) |
| Минимальный SDK | 26 (Android 8.0) |
| Целевой SDK | 34 (Android 14) |
| Сборка | Gradle 8.6 + AGP 8.2.2 |
| Подпись | keystore `~/bus127.keystore` (alias `bus127`) |
## Пуш-уведомления (RuStore)
Приложение интегрировано с [RuStore Push SDK](https://www.rustore.ru/help/sdk/push-notifications)
(аналог Firebase Cloud Messaging). Проект в консоли RuStore привязан к пакету
`ru.ua1zbe.bus127` и подписи release-keystore; пока подпись не меняется, перерегистрация не нужна.
Для доставки на устройстве должен быть установлен и авторизован **RuStore**.
Рассылка выполняется с сервера через API RuStore:
```
POST https://vkpns.rustore.ru/v1/projects/{project_id}/messages:send
Authorization: Bearer {service-token}
Content-Type: application/json
{
"message": {
"token": "{push-token устройства}",
"notification": {
"title": "Автобус 127",
"body": "Ближайший рейс через 5 мин"
}
}
}
```
- `project_id` и `service-token` берутся в консоли RuStore: **Push-уведомления > Проекты**.
В приложение попадает только `project_id`; сервисный токен в APK не хранится.
- `push-token` устройства приходит в `onNewToken` (лог `RuStorePush`) и сохраняется
в `SharedPreferences` `bus127_push`.
- Приложение подписывается на топик `bus127` при старте. Отдельного создания топика
в консоли не требуется — публикация в него проходит и для несуществующего.
- Если в запросе есть секция `notification` — уведомление показывает сам SDK;
если переданы только `data` (`title`/`body`, необязательный `url`) — приложение
показывает его само и открывает ссылку по клику.
### Рассылка
**Всем подписчикам топика** (все устройства, открывшие приложение):
```
POST https://vkpns-topics.rustore.ru/v1/projects/{project_id}/topics/{topic}/publish
Authorization: Bearer {service-token}
{"message":{"notification":{"title":"...","body":"..."}}}
```
**Одному устройству** — по его push-токену:
```
POST https://vkpns.rustore.ru/v1/projects/{project_id}/messages:send
Authorization: Bearer {service-token}
{"message":{"token":"...","notification":{"title":"...","body":"..."}}}
```
Если устройства не подписались сами, их токены можно подписать разом:
`POST .../topics/{topic}/batch_subscribe` с `{"push_tokens":[...]}`.
Ответ `400` с текстом про `registration token` означает, что адресат не указан
или токен устройства неверен; `401`/`403` — неверный сервисный токен или его пара с `project_id`.
## Структура
```
apk-webview/ # исходники APK (WebView)
├── app/
│ ├── build.gradle
│ └── src/main/
│ ├── AndroidManifest.xml
│ ├── java/ru/ua1zbe/bus127/
│ │ ├── MainActivity.java # главный экран: WebView + запрос разрешения
│ │ ├── AboutActivity.java # окно «О приложении»
│ │ ├── MapActivity.java # экран карты (свой WebView на тот же index.html#map)
│ │ ├── Webs.java # общий WebView для всех экранов
│ │ ├── BusBridge.java # мост страницы и приложения (меню, назад, версия)
│ │ ├── Bus127App.java # инициализация RuStore Push SDK
│ │ ├── PushMessagingService.java # приём уведомлений
│ │ ├── PushIntents.java # переход по клику
│ │ └── push/PushStore.java # хранение push-токена
│ ├── assets/index.html # интерфейс (HTML/JS)
│ ├── assets/route.js # геометрия маршрута OSRM + координаты остановок ([lat,lon])
│ ├── assets/mmr-gl.js # VK Maps SDK (UMD, глобаль mmrgl), BSD-3-Clause
│ ├── assets/mmr-gl.css # стили SDK
│ └── res/values/strings.xml
└── settings.gradle, build.gradle, gradle.properties
web/index.html # веб-версия (та же страница, для браузера)
```
## Сборка
```bash
export JAVA_HOME=$HOME/jdk-17.0.20.1+1
export ANDROID_HOME=$HOME/Android/Sdk
cd apk-webview
~/gradle-8.6/bin/gradle assembleRelease --no-daemon
```
Готовый APK — в [релизах](../../releases) и в репозитории `android_apk`.
## Лицензия
MIT. В `app/src/main/assets/` лежит сторонний код со своей лицензией:
- `mmr-gl.js`, `mmr-gl.css` — VK Maps SDK, BSD-3-Clause,
текст в `mmr-gl.LICENSE.txt`;
- `route.js` — геометрия дороги и координаты остановок из OpenStreetMap
(ODbL), атрибуция также выводится самими VK Картами.