commit 858f21e8d934177478c406a01ff8e2f40aa0d60a Author: ua1zbe Date: Fri Aug 28 22:06:07 2026 +0300 Initial: BusSchedule127 Android app (Kotlin, dark theme, bus icon) - Расписание автобуса №127 Полярные Зори — Зашеек - Вкладки Будни/Суббота/Воскресенье - Ближайшие рейсы с подсчётом 'через N мин' (МСК) - Тёмная тема, Material-карточки, чипы расписания - Адаптивная иконка-автобус diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c6f0b08 --- /dev/null +++ b/.gitignore @@ -0,0 +1,42 @@ +# Built application files +*.apk +*.aar +*.ap_ +*.aab + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ +release/ + +# Gradle files +.gradle/ +build/ +gradle-8.6/ +gradle-8.6-bin.zip +!gradle/wrapper/gradle-wrapper.jar + +# Local configuration file (sdk path, etc) +local.properties + +# Signing keys +*.keystore +*.jks + +# Log/OS Files +*.log + +# Android Studio / IntelliJ +*.iml +.idea/ +.DS_Store +captures/ +.externalNativeBuild/ +.cxx/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..785d3fd --- /dev/null +++ b/README.md @@ -0,0 +1,78 @@ +# Автобус №127 — Расписание (Android) + +[![Лицензия: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](#лицензия) + +Приложение для Android с расписанием автобуса **№127** по маршруту +**Полярные Зори ⇄ Зашеек** (Мурманская область, Кандалакшский район). +Написано на **Kotlin** с использованием **Android SDK** и Material Components. +Тёмная тема, аккуратные карточки и «чипы» расписания. + +## Возможности + +- Расписание на **будни**, **субботу** и **воскресенье** (переключатель вкладок). +- Блок **«Ближайшие рейсы»** — три ближайших отправления с подсчётом + «через N минут» (время по **МСК**, обновляется каждые 30 сек). +- Полные списки рейсов **туда** (ПЗ → Зашеек) и **обратно** (Зашеек → ПЗ), + аккуратно переносящиеся по 5 в строке. +- Тёмная тема (#121212) с оранжево-красным акцентом. +- Адаптивная иконка-автобус (Adaptive Icon). +- Живые часы местного времени (МСК) в шапке. + +## Скриншот + +Иконка приложения — стилизованный автобус на градиентном фоне. + +## Технические данные + +| Параметр | Значение | +|-----------------|-----------------------------------| +| Язык | Kotlin 1.9.22 | +| Минимальный SDK | 26 (Android 8.0) | +| Целевой SDK | 34 (Android 14) | +| Сборка | Gradle 8.6 + Android Gradle Plugin 8.2.2 | +| UI | Material Components, ConstraintLayout | + +## Сборка + +Проект собирается системным Gradle (на хосте `192.168.1.46` gradle распакован +в `~/BusSchedule127/gradle-8.6`): + +```bash +export ANDROID_HOME=~/Android/Sdk +export JAVA_HOME=/usr +export PATH=$PATH:~/BusSchedule127/gradle-8.6/bin + +cd BusSchedule127 +gradle clean assembleRelease --no-daemon +``` + +Подписанный APK появится в: +`app/build/outputs/apk/release/app-release.apk` + +> Для подписи используется keystore `~/bus127.keystore` (alias `bus127`). +> Секретные ключи в репозиторий не включены — генерируйте свои +> через `keytool` перед релизной сборкой. + +## Структура + +``` +BusSchedule127/ +├── app/ +│ ├── build.gradle +│ └── src/main/ +│ ├── AndroidManifest.xml +│ ├── java/ru/ua1zbe/bus127/MainActivity.kt +│ └── res/ +│ ├── drawable/ # фоны, чипы, иконка-автобус +│ ├── layout/ # activity_main.xml +│ ├── mipmap-anydpi-v26/ # адаптивная иконка +│ └── values/ # colors, strings, themes +├── build.gradle +├── settings.gradle +├── gradle.properties +└── README.md +``` + +## Лицензия + +MIT — свободное использование и модификация. diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..264fdb1 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,46 @@ +plugins { + id 'com.android.application' + id 'org.jetbrains.kotlin.android' +} + +android { + namespace 'ru.ua1zbe.bus127' + compileSdk 34 + + defaultConfig { + applicationId "ru.ua1zbe.bus127" + minSdk 26 + targetSdk 34 + versionCode 1 + versionName "1.0" + } + + signingConfigs { + release { + storeFile file(System.getProperty("user.home") + "/bus127.keystore") + storePassword "ktdbycrbq1980" + keyAlias "bus127" + keyPassword "ktdbycrbq1980" + } + } + buildTypes { + release { + minifyEnabled false + signingConfig signingConfigs.release + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + kotlinOptions { + jvmTarget = '17' + } +} + +dependencies { + implementation 'androidx.core:core-ktx:1.12.0' + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'com.google.android.material:material:1.11.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..7ab27c3 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/java/ru/ua1zbe/bus127/MainActivity.kt b/app/src/main/java/ru/ua1zbe/bus127/MainActivity.kt new file mode 100644 index 0000000..e0bfd89 --- /dev/null +++ b/app/src/main/java/ru/ua1zbe/bus127/MainActivity.kt @@ -0,0 +1,191 @@ +package ru.ua1zbe.bus127 + +import android.graphics.Color +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.widget.Button +import android.widget.LinearLayout +import android.widget.TextView +import androidx.appcompat.app.AppCompatActivity +import java.time.Duration +import java.time.LocalTime +import java.time.ZoneId +import java.time.format.DateTimeFormatter + +class MainActivity : AppCompatActivity() { + + private val mskZone = ZoneId.of("Europe/Moscow") + + private val schedule = mapOf( + "weekday" to Pair( + listOf("06:20","07:00","08:30","10:35","11:50","12:20","13:20","14:20","14:50","16:20","17:40","19:10","21:10"), + listOf("06:30","07:25","09:00","11:05","12:20","12:50","13:50","14:50","15:25","17:00","18:10","19:40","21:40") + ), + "saturday" to Pair( + listOf("07:00","08:20","09:35","11:00","13:20","14:50","16:20","17:50","19:00","21:10"), + listOf("07:25","08:45","10:05","11:30","13:50","15:45","16:45","18:20","19:30","21:40") + ), + "sunday" to Pair( + listOf("07:00","09:35","13:20","14:50","17:40","21:10"), + listOf("07:25","10:05","13:50","15:25","18:10","21:40") + ) + ) + + private val dayKeys = listOf("weekday", "saturday", "sunday") + private var selectedDay = 0 + + private lateinit var nearContainer: LinearLayout + private lateinit var toContainer: LinearLayout + private lateinit var backContainer: LinearLayout + private lateinit var dayButtons: List