Compare commits
94
Commits
v1.0.3
..
ea44cf5d2e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea44cf5d2e | ||
|
|
984feb170a | ||
|
|
5691c87e91 | ||
|
|
227e08a671 | ||
|
|
3bfb5f9788 | ||
|
|
bf1cf3865a | ||
|
|
0c3bed6213 | ||
|
|
f1cb2d618d | ||
|
|
8c9a3b5b37 | ||
|
|
de8510bc79 | ||
|
|
34d01b312e | ||
|
|
f89332b28c | ||
|
|
8f12bf32bc | ||
|
|
b9ae128842 | ||
|
|
a86dca50b8 | ||
|
|
fc49eae512 | ||
|
|
ffbae9edfd | ||
|
|
2268c64250 | ||
|
|
c954fd9bb8 | ||
|
|
b9757348f2 | ||
|
|
130f8bbecc | ||
|
|
4c00d46a14 | ||
|
|
07fc4021e1 | ||
|
|
431436d0db | ||
|
|
905711d8de | ||
|
|
7c9cb3fb0d | ||
|
|
ae0d1b2d3d | ||
|
|
c5b3c5dae9 | ||
|
|
3fa3b4eac1 | ||
|
|
197bcc6f5e | ||
|
|
f4f5cec2be | ||
|
|
5a630f8401 | ||
|
|
54a3c58a22 | ||
|
|
1c6a044c37 | ||
|
|
fcc022db64 | ||
|
|
a908a2da18 | ||
|
|
2c25647fa5 | ||
|
|
956f33140e | ||
|
|
7bba4dc878 | ||
|
|
89235fbb46 | ||
|
|
0564101e9e | ||
|
|
2baa544b32 | ||
|
|
f9c3a2e305 | ||
|
|
e49e7c358e | ||
|
|
3267fee439 | ||
|
|
8a0651e578 | ||
|
|
32d45f6430 | ||
|
|
4a06e9da8b | ||
|
|
d6b36a1d3a | ||
|
|
e811b4bc43 | ||
|
|
5d3b355163 | ||
|
|
81f3b05653 | ||
|
|
37407e2737 | ||
|
|
13159c576e | ||
|
|
1834763f19 | ||
|
|
62c0469669 | ||
|
|
3d6e1624e9 | ||
|
|
b1a34105f1 | ||
|
|
72db88b25c | ||
|
|
97f0eb56d5 | ||
|
|
c6d6392656 | ||
|
|
958fb6eaa6 | ||
|
|
2c806ef14e | ||
|
|
0bbdbdb4f1 | ||
|
|
fe2e2e589a | ||
|
|
e0115e85fc | ||
|
|
0e15d5f9a4 | ||
|
|
5555676395 | ||
|
|
ca512f5993 | ||
|
|
64d6f5a41d | ||
|
|
a3d39764e2 | ||
|
|
705b8904a4 | ||
|
|
541dda292f | ||
|
|
fa98451533 | ||
|
|
ee9d8cdbaf | ||
|
|
76326bbc27 | ||
|
|
ed02da031b | ||
|
|
a4e24da717 | ||
|
|
ab84205bec | ||
|
|
9ba1b1fa13 | ||
|
|
06557e77b8 | ||
|
|
a08fe31d3d | ||
|
|
060896d12b | ||
|
|
1a26817d2c | ||
|
|
693f879078 | ||
|
|
0bc592f357 | ||
|
|
9b6564eedd | ||
|
|
a66351a6f4 | ||
|
|
b034384ab2 | ||
|
|
621745a93c | ||
|
|
bf6e76dcbf | ||
|
|
18baec5020 | ||
|
|
2531ff2b9f | ||
|
|
983a77c9fb |
@@ -1,5 +1,13 @@
|
||||
.gradle/
|
||||
build/
|
||||
local.properties
|
||||
app/google-services.json
|
||||
app/google-services.json:Zone.Identifier
|
||||
*/build/
|
||||
*.iml
|
||||
keystore.properties
|
||||
*.jks
|
||||
release-artifacts/
|
||||
app/src/main/res_bak/
|
||||
scripts/*.json
|
||||
scripts/*.json:Zone.Identifier
|
||||
|
||||
@@ -21,3 +21,65 @@ Natywna aplikacja Android Jetpack Compose dla kierowcow TPP.
|
||||
```bash
|
||||
./gradlew :app:testDebugUnitTest
|
||||
```
|
||||
|
||||
## Release Gitea i Google Play
|
||||
|
||||
Przed wydaniem zapisz wszystkie zmiany źródłowe w commicie. Następnie uruchom:
|
||||
|
||||
```bash
|
||||
./scripts/release-android.sh
|
||||
```
|
||||
|
||||
Skrypt automatycznie zwiększa `versionCode` i ostatni człon `versionName`, uruchamia testy,
|
||||
buduje podpisany APK oraz AAB, a po poprawnym buildzie pyta, czy wysłać aktualizację do
|
||||
Google Play. Po odpowiedzi „tak” publikuje AAB w skonfigurowanym teście zamkniętym i
|
||||
wysyła zmiany do weryfikacji. Następnie tworzy commit wersji, tag, push i Gitea Release.
|
||||
Artefakty zostają również zapisane lokalnie w `release-artifacts/<tag>/`.
|
||||
|
||||
Do publikacji Google Play konto serwisowe musi mieć dla aplikacji
|
||||
`pl.firmatpp.kierowca` uprawnienia „Wyświetlanie informacji o aplikacji (tylko do odczytu)”
|
||||
oraz „Publikowanie aplikacji na ścieżkach testowych”. Pobrany klucz JSON umieść
|
||||
bezpośrednio w folderze `scripts`, na przykład:
|
||||
|
||||
```text
|
||||
scripts/google-play-service-account.json
|
||||
```
|
||||
|
||||
Skrypt sam znajduje jedyny plik `scripts/*.json`, sprawdza, czy jest prawidłowym kluczem
|
||||
konta serwisowego, i używa go do autoryzacji. Pliki `scripts/*.json` są ignorowane przez
|
||||
Git i nie mogą zostać przypadkowo dodane do repozytorium. Jeśli w folderze znajduje się
|
||||
więcej niż jeden prawidłowy klucz, skrypt przerwie działanie i poprosi o pozostawienie
|
||||
jednego.
|
||||
|
||||
`GOOGLE_PLAY_TRACK` musi być identyfikatorem istniejącego testu zamkniętego. Domyślna
|
||||
wartość to `alpha`. Opcjonalnie można ustawić `GOOGLE_PLAY_PACKAGE_NAME` i
|
||||
`GOOGLE_PLAY_RELEASE_LANGUAGE` (domyślnie `pl-PL`). Zmienna
|
||||
`GOOGLE_PLAY_SERVICE_ACCOUNT_CREDENTIALS` pozostaje opcjonalnym sposobem wskazania klucza
|
||||
spoza folderu `scripts`. Skrypt nie zapisuje tokenu ani klucza w repozytorium; prywatny
|
||||
klucz tymczasowy jest usuwany po zakończeniu.
|
||||
|
||||
Przed zatwierdzeniem skrypt waliduje edycję Google Play. Commit edycji jawnie wysyła
|
||||
zmiany do weryfikacji. Jeżeli inne zmiany są już sprawdzane, skrypt nie anuluje ich —
|
||||
kończy się błędem i można go wznowić po zakończeniu poprzedniej weryfikacji.
|
||||
Jeżeli na koncie jest włączone publikowanie zarządzane, po akceptacji Google nadal trzeba
|
||||
wybrać „Opublikuj zmiany” w Play Console; bez publikowania zarządzanego zaakceptowane
|
||||
wydanie zostanie udostępnione testerom automatycznie.
|
||||
|
||||
Awaryjne wydanie wyłącznie do Gitea, bez Google Play:
|
||||
|
||||
```bash
|
||||
./scripts/release-android.sh --skip-google-play
|
||||
```
|
||||
|
||||
W środowisku bez interaktywnego terminala decyzję trzeba podać jawnie:
|
||||
|
||||
```bash
|
||||
./scripts/release-android.sh --publish-google-play
|
||||
```
|
||||
|
||||
Do autoryzacji Gitea używany jest `GITEA_TOKEN` albo dane zapisane w Git credential helper.
|
||||
Jeśli publikacja została przerwana już po utworzeniu commita wersji, można ją wznowić:
|
||||
|
||||
```bash
|
||||
./scripts/release-android.sh --reuse-current
|
||||
```
|
||||
|
||||
+65
-4
@@ -1,22 +1,65 @@
|
||||
import java.io.File
|
||||
import java.util.Properties
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
alias(libs.plugins.kotlin.compose)
|
||||
alias(libs.plugins.ksp)
|
||||
}
|
||||
|
||||
if (file("google-services.json").exists()) {
|
||||
apply(plugin = "com.google.gms.google-services")
|
||||
apply(plugin = "com.google.firebase.crashlytics")
|
||||
}
|
||||
|
||||
val keystorePropertiesFile = rootProject.file("keystore.properties")
|
||||
val keystoreProperties = Properties().apply {
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
keystorePropertiesFile.inputStream().use(::load)
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "pl.firmatpp.kierowca"
|
||||
compileSdk = 35
|
||||
compileSdk = 36
|
||||
|
||||
fun configValue(name: String, default: String): String =
|
||||
providers.gradleProperty(name)
|
||||
.orElse(providers.environmentVariable(name))
|
||||
.orElse(default)
|
||||
.get()
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "pl.firmatpp.kierowca"
|
||||
minSdk = 26
|
||||
targetSdk = 35
|
||||
versionCode = 4
|
||||
versionName = "1.0.3"
|
||||
targetSdk = 36
|
||||
versionCode = 122
|
||||
versionName = "1.0.69"
|
||||
setProperty("archivesBaseName", "pl.firmatpp.kierowca")
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
buildConfigField("String", "API_BASE_URL", "\"https://api-intranet.firmatpp.pl/api/\"")
|
||||
buildConfigField("String", "REVERB_APP_KEY", "\"${configValue("REVERB_APP_KEY", "")}\"")
|
||||
buildConfigField("String", "REVERB_WS_BASE_URL", "\"${configValue("REVERB_WS_BASE_URL", "wss://api-intranet.firmatpp.pl/app/")}\"")
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
create("release") {
|
||||
fun requiredSigningProperty(name: String): String =
|
||||
keystoreProperties.getProperty(name)
|
||||
?: throw GradleException("Missing '$name' in keystore.properties")
|
||||
|
||||
val configuredStoreFile = requiredSigningProperty("storeFile")
|
||||
storeFile = if (File(configuredStoreFile).isAbsolute) {
|
||||
file(configuredStoreFile)
|
||||
} else {
|
||||
rootProject.file(configuredStoreFile)
|
||||
}
|
||||
storePassword = requiredSigningProperty("storePassword")
|
||||
keyAlias = requiredSigningProperty("keyAlias")
|
||||
keyPassword = requiredSigningProperty("keyPassword")
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
@@ -24,7 +67,11 @@ android {
|
||||
isMinifyEnabled = false
|
||||
}
|
||||
release {
|
||||
signingConfig = signingConfigs.getByName("release")
|
||||
isMinifyEnabled = false
|
||||
ndk {
|
||||
debugSymbolLevel = "SYMBOL_TABLE"
|
||||
}
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
@@ -45,6 +92,10 @@ android {
|
||||
compose = true
|
||||
buildConfig = true
|
||||
}
|
||||
|
||||
lint {
|
||||
disable += "NullSafeMutableLiveData"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -57,6 +108,8 @@ dependencies {
|
||||
implementation(libs.androidx.lifecycle.runtime.compose)
|
||||
implementation(libs.androidx.lifecycle.viewmodel.compose)
|
||||
implementation(libs.androidx.navigation.compose)
|
||||
implementation(libs.androidx.room.ktx)
|
||||
implementation(libs.androidx.room.runtime)
|
||||
implementation(libs.androidx.work.runtime.ktx)
|
||||
implementation(libs.camera.camera2)
|
||||
implementation(libs.camera.core)
|
||||
@@ -64,15 +117,21 @@ dependencies {
|
||||
implementation(libs.camera.view)
|
||||
implementation(libs.coil.compose)
|
||||
implementation(libs.compose.material.icons.extended)
|
||||
implementation("androidx.compose.material:material")
|
||||
implementation(libs.compose.material3)
|
||||
implementation(libs.compose.ui)
|
||||
implementation(libs.compose.ui.graphics)
|
||||
implementation(libs.compose.ui.tooling.preview)
|
||||
implementation(libs.coroutines.android)
|
||||
implementation(platform(libs.firebase.bom))
|
||||
implementation(libs.firebase.crashlytics)
|
||||
implementation(libs.firebase.messaging)
|
||||
implementation(libs.okhttp)
|
||||
implementation(libs.okhttp.logging)
|
||||
implementation(libs.play.services.auth)
|
||||
implementation(libs.play.services.auth.api.phone)
|
||||
implementation(libs.play.app.update)
|
||||
implementation(libs.play.app.update.ktx)
|
||||
implementation(libs.retrofit)
|
||||
implementation(libs.retrofit.gson)
|
||||
|
||||
@@ -80,4 +139,6 @@ dependencies {
|
||||
|
||||
testImplementation(libs.junit)
|
||||
testImplementation(libs.coroutines.test)
|
||||
|
||||
ksp(libs.androidx.room.compiler)
|
||||
}
|
||||
|
||||
@@ -2,10 +2,29 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.camera"
|
||||
android:required="false" />
|
||||
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.speech.RecognitionService" />
|
||||
</intent>
|
||||
</queries>
|
||||
|
||||
<application
|
||||
android:allowBackup="false"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:name=".DriverApplication"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.TppKierowca">
|
||||
<activity
|
||||
@@ -26,5 +45,18 @@
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
|
||||
<service
|
||||
android:name=".sync.DriverFirebaseMessagingService"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name=".tracking.ActiveRouteTrackingService"
|
||||
android:exported="false"
|
||||
android:foregroundServiceType="location" />
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package pl.firmatpp.kierowca
|
||||
|
||||
import android.app.Application
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.launch
|
||||
import pl.firmatpp.kierowca.data.upload.OfflineOutboxManager
|
||||
import pl.firmatpp.kierowca.diagnostics.AppDiagnostics
|
||||
|
||||
class DriverApplication : Application() {
|
||||
private val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
AppDiagnostics.installFirebaseCrashlytics()
|
||||
AppDiagnostics.log("app_started")
|
||||
applicationScope.launch {
|
||||
val outboxManager = OfflineOutboxManager(this@DriverApplication)
|
||||
runCatching { outboxManager.repairOperationalQueues() }
|
||||
.onFailure { AppDiagnostics.reportNonFatal(it, "repair_operational_queues") }
|
||||
runCatching { outboxManager.repairGpsQueue() }
|
||||
.onFailure { AppDiagnostics.reportNonFatal(it, "repair_gps_queue") }
|
||||
}
|
||||
}
|
||||
}
|
||||