Skip to content

Commit 08ab47d

Browse files
committed
Apollo: Release source code for 55.4 (1504)
1 parent b544519 commit 08ab47d

File tree

246 files changed

+9636
-2563
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

246 files changed

+9636
-2563
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ This is the source code repository for muun's android wallet. Muun is a non-cust
66

77
## Runtime requirements
88

9-
* Android version 4.4 (API level 19) or higher
9+
* Android version 5.0 (API level 21) or higher
1010
* Google Play services
1111

1212
## Structure

android/CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,22 @@ follow [https://changelog.md/](https://changelog.md/) guidelines.
66

77
## [Unreleased]
88

9+
## [55.4] - 2026-01-29
10+
11+
### CHANGED
12+
13+
- Bump `minSdk` to 21
14+
- 6-digit pin for new users
15+
- Replace ButterKnife with ViewBinding in various screens
16+
17+
### ADDED
18+
19+
- Biometrics support for app unlocking
20+
21+
### FIXED
22+
23+
- Input fee bug not recognizing decimal separator in Spanish
24+
925
## [55.3] - 2025-10-08
1026

1127
### CHANGED
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,15 @@
22
**
33

44
# ⚠️ whitelist only necessary things
5+
!.git/
56
!android/
6-
!tools/
7+
!common/
8+
!gradlew
9+
!gradle.properties
10+
!gradle/
11+
!build.gradle
12+
!settings.gradle
713
!libwallet/
14+
!linters/
815
!prover/
16+
!tools/

android/apolloui/build.gradle

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ apply from: "${project.rootDir}/linters/pmd/check-android.gradle"
3535

3636

3737
check.dependsOn 'lint'
38+
tasks.matching { it.name.startsWith('lint') }.configureEach {task ->
39+
task.dependsOn(':common:animalsnifferMain')
40+
}
3841

3942
/**
4043
* Insert quotes around string fields that are injected literally into code, like a C macro.
@@ -87,7 +90,7 @@ static def configExternalLinks(productFlavor, String host) {
8790
android {
8891
namespace "io.muun.apollo"
8992

90-
compileSdk 34
93+
compileSdk 35
9194

9295
buildFeatures {
9396
viewBinding true
@@ -96,17 +99,13 @@ android {
9699

97100
defaultConfig {
98101
applicationId "io.muun.apollo"
99-
minSdk 19
102+
minSdk 21
100103
targetSdk 35
101-
versionCode 1503
102-
versionName "55.3"
103-
104-
// Needed to make sure these classes are available in the main DEX file for API 19
105-
// See: https://spin.atomicobject.com/2018/07/16/support-kitkat-multidex/
106-
multiDexKeepProguard file('./proguard/proguard-multidex.pro')
104+
versionCode 1504
105+
versionName "55.4"
107106

108107
// Use default Proguard file, bundled with Android Gradle Plugin
109-
// See: https://foreachi.com/android/androidx-proguard/
108+
// See: https://issuetracker.google.com/issues/126772206
110109
proguardFiles getDefaultProguardFile("proguard-android.txt")
111110
proguardFiles files {
112111
file('./proguard').listFiles().findAll { it.path.endsWith('.pro') }
@@ -146,7 +145,6 @@ android {
146145
versionNameSuffix "-debug"
147146

148147
debuggable true
149-
multiDexEnabled true
150148
minifyEnabled false
151149
shrinkResources false
152150

@@ -165,14 +163,12 @@ android {
165163
// Debuggable enabled has priority over the other flags, and those optimizations are going to be disabled.
166164
minified {
167165
debuggable true
168-
multiDexEnabled true
169166
minifyEnabled true
170167
shrinkResources true
171168
}
172169

173170
release {
174171
debuggable false
175-
multiDexEnabled true
176172
minifyEnabled true
177173
shrinkResources true
178174

@@ -455,8 +451,7 @@ dependencies {
455451
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.1"
456452

457453
// Detect root devices (for error reports metadata and fraud control)
458-
// TODO: go back to `com.scottyab:rootbeer-lib:x.x.x` after dropping API 19 support
459-
implementation 'com.github.muun:rootbeer:0.1.0'
454+
implementation 'com.scottyab:rootbeer-lib:0.1.1'
460455

461456
// Google Play Integrity
462457
implementation 'com.google.android.play:integrity:1.1.0'
@@ -490,11 +485,11 @@ dependencies {
490485
implementation 'androidx.preference:preference:1.0.0'
491486
def emojiVersion = "1.1.0" // We need targetSdkVersion 32 to bump
492487
implementation "androidx.emoji2:emoji2:$emojiVersion"
493-
implementation "androidx.activity:activity:1.8.2"
488+
// We need targetSdkVersion 36 to bump
489+
implementation "androidx.activity:activity-ktx:1.10.1"
494490

495491
// Remove gridlayout-v7 once we drop minSDK version 19
496492
implementation 'androidx.gridlayout:gridlayout:1.0.0'
497-
implementation 'androidx.multidex:multidex:2.0.0'
498493
// We need to specify versions for customtabs and cardview because some dependencies use them
499494
implementation 'androidx.browser:browser:1.0.0'
500495
implementation 'androidx.cardview:cardview:1.0.0'
@@ -577,6 +572,9 @@ dependencies {
577572

578573
// Fancy animations
579574
implementation 'com.airbnb.android:lottie:3.5.0'
575+
576+
// Biometrics
577+
implementation 'androidx.biometric:biometric:1.4.0-alpha04'
580578
}
581579

582580
configurations {

android/apolloui/proguard/proguard-multidex.pro

Lines changed: 0 additions & 16 deletions
This file was deleted.

android/apolloui/src/main/AndroidManifest.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
xmlns:tools="http://schemas.android.com/tools"
44
>
55

6+
<uses-sdk tools:overrideLibrary="androidx.biometric, androidx.biometric.ktx" />
7+
68
<!-- Permissions -->
79

810
<uses-feature android:name="android.hardware.camera"/>
@@ -418,6 +420,12 @@
418420
/>
419421

420422
<!-- Providers -->
423+
<provider
424+
android:name=".presentation.app.trace.StartupTraceProvider"
425+
android:authorities="${applicationId}.muun-tracer"
426+
android:exported="false">
427+
</provider>
428+
421429
<provider
422430
android:name="androidx.core.content.FileProvider"
423431
android:authorities="${applicationId}.cache.fileprovider"

android/apolloui/src/main/java/io/muun/apollo/data/afs/ActivityManagerInfoProvider.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class ActivityManagerInfoProvider(context: Context) {
6464

6565
val exitReasons: List<ApplicationExitInfo>
6666
get() {
67-
return if (OS.supportsgetHistoricalProcessExitReasons()) {
67+
return if (OS.supportsGetHistoricalProcessExitReasons()) {
6868
activityManager.getHistoricalProcessExitReasons(
6969
Globals.INSTANCE.applicationId,
7070
0,
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package io.muun.apollo.data.afs
2+
3+
import org.threeten.bp.Instant
4+
import org.threeten.bp.ZoneOffset
5+
6+
object AfsUtils {
7+
/**
8+
* Normalizes the given epoch time to UTC midnight, reducing it to day-level granularity.
9+
*
10+
* The returned value represents the epoch at 00:00:00.000 UTC of the same day
11+
* as the input timestamp.
12+
*/
13+
@JvmStatic
14+
fun epochAtUtcMidnight(epochMillis: Long): Long {
15+
return Instant.ofEpochMilli(epochMillis)
16+
.atZone(ZoneOffset.UTC)
17+
.toLocalDate()
18+
.atStartOfDay(ZoneOffset.UTC)
19+
.toInstant()
20+
.toEpochMilli()
21+
}
22+
}

android/apolloui/src/main/java/io/muun/apollo/data/afs/BackgroundExecutionMetricsProvider.kt

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
package io.muun.apollo.data.afs
22

3+
import io.muun.apollo.data.os.GooglePlayHelper
4+
import io.muun.apollo.data.os.GooglePlayServicesHelper
35
import io.muun.apollo.domain.model.BackgroundEvent
46
import kotlinx.serialization.Serializable
57
import javax.inject.Inject
68

79
class BackgroundExecutionMetricsProvider @Inject constructor(
8-
private val metricsProvider: MetricsProvider
10+
private val metricsProvider: MetricsProvider,
11+
private val googlePlayServicesHelper: GooglePlayServicesHelper,
12+
private val googlePlayHelper: GooglePlayHelper,
913
) {
1014

15+
private val playServicesInfo = googlePlayServicesHelper.getPlayServicesInfo()
16+
1117
fun run(): BackgroundExecutionMetrics =
1218
BackgroundExecutionMetrics(
1319
metricsProvider.currentTimeMillis,
@@ -33,9 +39,9 @@ class BackgroundExecutionMetricsProvider @Inject constructor(
3339
metricsProvider.bridgeEnabled,
3440
metricsProvider.bridgeDaemonStatus,
3541
metricsProvider.developerEnabled,
36-
metricsProvider.proxyHttp,
37-
metricsProvider.proxyHttps,
38-
metricsProvider.proxySocks,
42+
metricsProvider.proxyHttpType,
43+
metricsProvider.proxyHttpsType,
44+
metricsProvider.proxySocksType,
3945
metricsProvider.autoDateTime,
4046
metricsProvider.autoTimeZone,
4147
metricsProvider.timeZoneId,
@@ -55,7 +61,18 @@ class BackgroundExecutionMetricsProvider @Inject constructor(
5561
metricsProvider.latestBackgroundTimes,
5662
metricsProvider.internalLevel.let { "${it.first};${it.second}" },
5763
metricsProvider.batteryRemainState,
58-
metricsProvider.isCharging
64+
metricsProvider.isCharging,
65+
metricsProvider.defaultFsDate,
66+
metricsProvider.androidFsDate,
67+
metricsProvider.hasUniqueBaseDateInExternalStorage,
68+
metricsProvider.externalStorageMinDate,
69+
metricsProvider.hasNewEntriesInAppExternalStorage,
70+
playServicesInfo.versionCode,
71+
playServicesInfo.versionName,
72+
playServicesInfo.clientVersionCode,
73+
googlePlayHelper.versionCode,
74+
googlePlayHelper.versionName,
75+
metricsProvider.buildInfo
5976
)
6077

6178
@Suppress("ArrayInDataClass")
@@ -84,9 +101,9 @@ class BackgroundExecutionMetricsProvider @Inject constructor(
84101
private val bridgeEnabled: Int,
85102
private val bridgeDaemonStatus: String,
86103
private val developerEnabled: Int,
87-
private val proxyHttp: String,
88-
private val proxyHttps: String,
89-
private val proxySocks: String,
104+
private val proxyHttpType: Int,
105+
private val proxyHttpsType: Int,
106+
private val proxySocksType: Int,
90107
private val autoDateTime: Int,
91108
private val autoTimeZone: Int,
92109
private val timeZoneId: String,
@@ -106,6 +123,17 @@ class BackgroundExecutionMetricsProvider @Inject constructor(
106123
private val bkgTimes: List<BackgroundEvent>,
107124
private val internalLevel: String,
108125
private val batteryRemainState: String,
109-
private val isCharging: Boolean?
126+
private val isCharging: Boolean?,
127+
private val defaultFsDate: Long,
128+
private val androidFsDate: Long,
129+
private var hasUniqueBaseDateInExternalStorage: Int,
130+
private var externalStorageMinDate: Long,
131+
private var hasNewEntriesInAppExternalStorage: Int,
132+
private var googlePlayServicesVersionCode: Long,
133+
private var googlePlayServicesVersionName: String,
134+
private var googlePlayServicesClientVersionCode: Int,
135+
private var googlePlayVersionCode: Long,
136+
private var googlePlayVersionName: String,
137+
private var buildInfo: BuildInfo
110138
)
111139
}

android/apolloui/src/main/java/io/muun/apollo/data/afs/BuildInfo.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ data class BuildInfo(
88
val bootloader: String,
99
val manufacturer: String,
1010
val brand: String,
11+
val display: String,
1112
val host: String,
1213
val type: String,
1314
val radioVersion: String?,
1415
val securityPatch: String,
15-
// These fields are null on older app versions
16-
val model: String?,
17-
val product: String?,
18-
val release: String?
16+
val model: String,
17+
val product: String,
18+
val release: String,
19+
val date: Long
1920
)

0 commit comments

Comments
 (0)