Skip to content

Commit 81b191f

Browse files
authored
Merge pull request #28 from androidseb25/dev
Version 2.0.1 (21)
2 parents 2c6185d + 8b54f67 commit 81b191f

File tree

16 files changed

+807
-87
lines changed

16 files changed

+807
-87
lines changed
Lines changed: 104 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,41 @@
1-
name: Android Release
1+
name: Build Android APK
22

33
on:
44
push:
5-
branches: [ "main" ]
6-
workflow_dispatch: {}
7-
8-
permissions:
9-
contents: write # notwendig, um Releases/Tags anzulegen
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
108

119
jobs:
12-
build-release:
10+
build:
11+
name: Build APK
1312
runs-on: ubuntu-latest
1413

15-
env:
16-
# Pfade an dein Modul anpassen, falls nicht "app"
17-
APP_MODULE: app
18-
1914
steps:
20-
- name: Checkout
15+
- name: Checkout repository
2116
uses: actions/checkout@v4
2217

23-
- name: Setup JDK 17
24-
uses: actions/setup-java@v4
18+
- name: Set up JDK
19+
uses: actions/setup-java@v3
2520
with:
26-
distribution: temurin
27-
java-version: "17"
28-
cache: gradle
29-
30-
- name: Setup Android SDK
31-
uses: android-actions/setup-android@v3
32-
33-
- name: Decode signing keystore
34-
if: ${{ env.ANDROID_KEYSTORE_BASE64 != '' }}
35-
shell: bash
36-
env:
37-
ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
38-
run: |
39-
echo "$ANDROID_KEYSTORE_BASE64" | base64 -d > keystore.jks
40-
echo "ANDROID_KEYSTORE_PATH=$GITHUB_WORKSPACE/keystore.jks" >> $GITHUB_ENV
21+
distribution: 'temurin'
22+
java-version: '17'
4123

42-
- name: Make gradlew executable
43-
run: chmod +x gradlew
24+
- name: Setup Gradle cache
25+
uses: gradle/actions/setup-gradle@v5
4426

4527
# ---- Version aus Gradle lesen ----
4628
- name: Read versionName from Gradle
4729
id: ver
4830
run: |
49-
VERSION_NAME=$(./gradlew -q :${{ env.APP_MODULE }}:printVersionName)
31+
VERSION_NAME=$(./gradlew -q :app:printVersionName)
5032
echo "version_name=$VERSION_NAME" >> $GITHUB_OUTPUT
5133
52-
# ---- Release Build (APK & AAB) ----
53-
- name: Build Release APK
54-
run: ./gradlew :${{ env.APP_MODULE }}:assembleRelease
34+
- name: Build debug APK
35+
run: ./gradlew assembleDebug
5536

56-
- name: Build Release AAB
57-
run: ./gradlew :${{ env.APP_MODULE }}:bundleRelease
37+
- name: Build debug AAB
38+
run: ./gradlew bundleDebug
5839

5940
# ---- Artefakte umbenennen ----
6041
- name: Rename outputs to the correct version
@@ -63,14 +44,14 @@ jobs:
6344
set -e
6445
VER="${{ steps.ver.outputs.version_name }}"
6546
66-
APK_SRC="${{ env.APP_MODULE }}/build/outputs/apk/release"
67-
AAB_SRC="${{ env.APP_MODULE }}/build/outputs/bundle/release"
47+
APK_SRC="app/build/outputs/apk/debug"
48+
AAB_SRC="app/build/outputs/bundle/debug"
6849
6950
APK_PATH=$(ls "$APK_SRC"/*.apk | head -n1)
7051
AAB_PATH=$(ls "$AAB_SRC"/*.aab | head -n1)
7152
72-
APK_OUT="ipv64net_v${VER}.apk"
73-
AAB_OUT="ipv64net_v${VER}.aab"
53+
APK_OUT="ipv64net_v${VER}-debug.apk"
54+
AAB_OUT="ipv64net_v${VER}-debug.aab"
7455
7556
cp "$APK_PATH" "$APK_OUT"
7657
cp "$AAB_PATH" "$AAB_OUT"
@@ -83,21 +64,96 @@ jobs:
8364
- name: Upload artifacts
8465
uses: actions/upload-artifact@v4
8566
with:
86-
name: ipv64net-${{ steps.rename.outputs.version }}
67+
name: ipv64net-${{ steps.rename.outputs.version }}-debug
8768
path: |
8869
${{ steps.rename.outputs.apk }}
8970
${{ steps.rename.outputs.aab }}
9071
72+
- name: Decode keystore
73+
if: ${{ env.ANDROID_KEYSTORE_BASE64 != '' }}
74+
env:
75+
ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
76+
run: echo "$ANDROID_KEYSTORE_BASE64" | base64 -d > releaseKey.jks
77+
78+
- name: Build release APK
79+
run: ./gradlew assembleRelease
80+
81+
- name: Build release AAB
82+
run: ./gradlew bundleRelease
83+
84+
- name: Sign APK
85+
run: |
86+
jarsigner -verbose -sigalg SHA256withRSA -digestalg SHA-256 \
87+
-keystore releaseKey.jks -storepass ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} \
88+
-keypass ${{ secrets.ANDROID_KEY_PASSWORD }} \
89+
app/build/outputs/apk/release/app-release-unsigned.apk ${{ secrets.ANDROID_KEY_ALIAS }}
90+
91+
- name: Verify signature
92+
run: jarsigner -verify -verbose -certs app/build/outputs/apk/release/app-release-unsigned.apk
93+
94+
- name: Align APK
95+
run: |
96+
$ANDROID_HOME/build-tools/34.0.0/zipalign -v 4 \
97+
app/build/outputs/apk/release/app-release-unsigned.apk \
98+
app/build/outputs/apk/release/app-release.apk
99+
100+
# ======= AAB signieren (falls NICHT schon durch Gradle gesigned) =======
101+
# Wenn du signingConfigs.release in Gradle mit releaseKey.jks verwendest,
102+
# ist das AAB bereits signiert und du kannst diesen Schritt weg lassen.
103+
- name: Sign AAB (optional)
104+
if: ${{ env.ANDROID_KEYSTORE_BASE64 != '' }}
105+
env:
106+
ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
107+
run: |
108+
jarsigner -verbose -sigalg SHA256withRSA -digestalg SHA-256 \
109+
-keystore releaseKey.jks -storepass ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} \
110+
-keypass ${{ secrets.ANDROID_KEY_PASSWORD }} \
111+
app/build/outputs/bundle/release/app-release.aab ${{ secrets.ANDROID_KEY_ALIAS }}
112+
113+
- name: Verify AAB signature
114+
run: jarsigner -verify -verbose -certs app/build/outputs/bundle/release/app-release.aab
115+
116+
# ---- Artefakte umbenennen ----
117+
- name: Rename outputs to the correct version
118+
id: renamesign
119+
run: |
120+
set -e
121+
VER="${{ steps.ver.outputs.version_name }}"
122+
123+
APK_SRC="app/build/outputs/apk/release"
124+
AAB_SRC="app/build/outputs/bundle/release"
125+
126+
APK_PATH=$(ls "$APK_SRC"/*release.apk | head -n1)
127+
AAB_PATH=$(ls "$AAB_SRC"/*release.aab | head -n1)
128+
129+
APK_OUT="ipv64net_v${VER}-signed.apk"
130+
AAB_OUT="ipv64net_v${VER}-signed.aab"
131+
132+
cp "$APK_PATH" "$APK_OUT"
133+
cp "$AAB_PATH" "$AAB_OUT"
134+
135+
echo "apk=$APK_OUT" >> $GITHUB_OUTPUT
136+
echo "aab=$AAB_OUT" >> $GITHUB_OUTPUT
137+
echo "version=$VER" >> $GITHUB_OUTPUT
138+
139+
- name: Upload Signed APK & AAB
140+
uses: actions/upload-artifact@v4
141+
with:
142+
name: ipv64net-${{ steps.renamesign.outputs.version }}-signed
143+
path: |
144+
${{ steps.renamesign.outputs.apk }}
145+
${{ steps.renamesign.outputs.aab }}
146+
91147
# ---- GitHub Release erzeugen + Dateien anhängen ----
92148
- name: Create GitHub Release
93149
uses: softprops/action-gh-release@v2
94150
with:
95-
tag_name: v${{ steps.rename.outputs.version }}
96-
name: "ipv64net v${{ steps.rename.outputs.version }}"
97-
draft: false
151+
tag_name: v${{ steps.renamesign.outputs.version }}
152+
name: "ipv64net v${{ steps.renamesign.outputs.version }}"
153+
draft: true
98154
prerelease: false
99155
files: |
100-
${{ steps.rename.outputs.apk }}
101-
${{ steps.rename.outputs.aab }}
156+
${{ steps.renamesign.outputs.apk }}
157+
${{ steps.renamesign.outputs.aab }}
102158
env:
103-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
159+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

app/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ android {
1212
applicationId = "de.rpicloud.ipv64net"
1313
minSdk = 28
1414
targetSdk = 36
15-
versionCode = 20
16-
versionName = "2.0.0"
15+
versionCode = 21
16+
versionName = "2.0.1"
1717

1818
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
1919
}

app/src/main/java/de/rpicloud/ipv64net/helper/Extensions.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ fun Date.formatGermanTime(): String {
2828
return format.format(this)
2929
}
3030

31+
fun Date.formatDbTime(): String {
32+
val format = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.GERMANY)
33+
return format.format(this)
34+
}
35+
3136
fun String.parseDbDate(): String {
3237
val dbFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US)
3338
val date: Date? = runCatching { dbFormat.parse(this) }.getOrNull()

app/src/main/java/de/rpicloud/ipv64net/helper/PreferencesManager.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class PreferencesManager {
99

1010
companion object {
1111
@SuppressLint("UseKtx")
12-
inline fun <reified T> saveList(ctx: Context, key: String, list: List<T>) {
12+
inline fun <reified T> saveList(ctx: Context, key: String, list: MutableList<T>) {
1313
val gson = Gson()
1414
val jsonText = gson.toJson(list)
1515
with(ctx.getSharedPreferences(key, Context.MODE_PRIVATE).edit()) {
@@ -58,11 +58,11 @@ class PreferencesManager {
5858
}
5959
}
6060

61-
inline fun <reified T> loadList(ctx: Context, key: String): List<T> {
61+
inline fun <reified T> loadList(ctx: Context, key: String): MutableList<T> {
6262
val gson = Gson()
6363
val preferences = ctx.getSharedPreferences(key, Context.MODE_PRIVATE)
6464
val jsonText = preferences.getString(key, "[]")
65-
val type = object : TypeToken<List<T>>() {}.type
65+
val type = object : TypeToken<MutableList<T>>() {}.type
6666
return gson.fromJson(jsonText, type)
6767
}
6868

app/src/main/java/de/rpicloud/ipv64net/main/activity/MainActivity.kt

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@ import androidx.navigation.compose.rememberNavController
3838
import de.rpicloud.ipv64net.R
3939
import de.rpicloud.ipv64net.helper.BiometricPromptManager
4040
import de.rpicloud.ipv64net.helper.PreferencesManager
41+
import de.rpicloud.ipv64net.main.startup.views.LoginView
4142
import de.rpicloud.ipv64net.main.views.AboutView
43+
import de.rpicloud.ipv64net.main.views.AccountDetailView
44+
import de.rpicloud.ipv64net.main.views.AccountEditView
4245
import de.rpicloud.ipv64net.main.views.AccountView
4346
import de.rpicloud.ipv64net.main.views.DomainDetailView
4447
import de.rpicloud.ipv64net.main.views.DomainDnsNewView
@@ -56,6 +59,7 @@ import de.rpicloud.ipv64net.main.views.SettingsView
5659
import de.rpicloud.ipv64net.models.Tab
5760
import de.rpicloud.ipv64net.models.Tabs
5861
import de.rpicloud.ipv64net.models.Tabs.Companion.AddItem
62+
import de.rpicloud.ipv64net.models.User
5963
import de.rpicloud.ipv64net.ui.theme.AppTheme
6064

6165
class MainActivity : AppCompatActivity() {
@@ -66,17 +70,24 @@ class MainActivity : AppCompatActivity() {
6670

6771
override fun onCreate(savedInstanceState: Bundle?) {
6872
super.onCreate(savedInstanceState)
73+
User.init(applicationContext)
6974
enableEdgeToEdge()
7075
setContent {
7176
val navController = rememberNavController()
77+
val navBackStackEntry by navController.currentBackStackEntryAsState()
78+
val currentRoute = navBackStackEntry?.destination?.route
79+
7280
AppTheme {
7381

7482
val isBiometric: Boolean = PreferencesManager.loadBool(applicationContext, "LOCKSCREEN_ENABLED")
7583
val biometricResult by promptManager.promptResults.collectAsState(initial = null)
7684
val enrollLauncher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { println("Activity result $it") }
7785

7886
if (!isBiometric || biometricResult == BiometricPromptManager.BiometricResult.AuthenticationSuccess) {
79-
Scaffold(bottomBar = { TabView(Tabs.tabList, navController) }) { mainPadding ->
87+
Scaffold(bottomBar = {
88+
if (currentRoute != Tabs.Companion.getRoute(Tab.login))
89+
TabView(Tabs.tabList, navController)
90+
}) { mainPadding ->
8091
NavHost(
8192
navController = navController,
8293
startDestination = Tabs.Companion.getRoute(Tab.domains)
@@ -117,6 +128,12 @@ class MainActivity : AppCompatActivity() {
117128
composable(Tabs.Companion.getRoute(Tab.account)) {
118129
AccountView(navController, mainPadding = mainPadding)
119130
}
131+
composable(Tabs.Companion.getRoute(Tab.account_details)) {
132+
AccountDetailView(navController, mainPadding = mainPadding)
133+
}
134+
composable(Tabs.Companion.getRoute(Tab.account_edit)) {
135+
AccountEditView(navController, mainPadding = mainPadding)
136+
}
120137
composable(Tabs.Companion.getRoute(Tab.logs)) {
121138
LogView(navController, mainPadding = mainPadding)
122139
}
@@ -126,6 +143,9 @@ class MainActivity : AppCompatActivity() {
126143
composable(Tabs.Companion.getRoute(Tab.about)) {
127144
AboutView(navController, mainPadding = mainPadding)
128145
}
146+
composable(Tabs.Companion.getRoute(Tab.login)) {
147+
LoginView(navController, true)
148+
}
129149
}
130150
}
131151
} else {

app/src/main/java/de/rpicloud/ipv64net/main/startup/activity/LoginActivity.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ import androidx.compose.material3.MaterialTheme
88
import androidx.compose.material3.Surface
99
import androidx.compose.ui.Modifier
1010
import androidx.navigation.compose.rememberNavController
11+
import de.rpicloud.ipv64net.models.User
1112
import de.rpicloud.ipv64net.ui.theme.AppTheme
1213

1314
class LoginActivity : ComponentActivity() {
1415
override fun onCreate(savedInstanceState: Bundle?) {
1516
super.onCreate(savedInstanceState)
17+
User.init(applicationContext)
1618
setContent {
1719
val navController = rememberNavController()
1820
AppTheme {

0 commit comments

Comments
 (0)