Skip to content

Commit 2e660ca

Browse files
Fix #11 intermittent app crash on first launch
2 parents c9593bb + 8959b00 commit 2e660ca

5 files changed

Lines changed: 68 additions & 11 deletions

File tree

app/build.gradle

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ android {
1818
minSdk 24
1919
targetSdk 34
2020
versionCode 1
21-
versionName "0.0.10"
21+
versionName "0.0.11"
2222
}
2323

2424
signingConfigs {
@@ -72,6 +72,12 @@ android {
7272
viewBinding true
7373
}
7474

75+
packaging {
76+
jniLibs {
77+
useLegacyPackaging = true
78+
}
79+
}
80+
7581
applicationVariants.all { variant ->
7682
variant.outputs.all { output ->
7783
def versionName = variant.versionName
@@ -96,10 +102,10 @@ dependencies {
96102
implementation "androidx.security:security-crypto:1.1.0-alpha06"
97103

98104
// CameraX dependencies
99-
implementation 'androidx.camera:camera-core:1.3.0'
100-
implementation 'androidx.camera:camera-camera2:1.3.0'
101-
implementation 'androidx.camera:camera-lifecycle:1.3.0'
102-
implementation 'androidx.camera:camera-view:1.3.0'
105+
implementation 'androidx.camera:camera-core:1.4.0'
106+
implementation 'androidx.camera:camera-camera2:1.4.0'
107+
implementation 'androidx.camera:camera-lifecycle:1.4.0'
108+
implementation 'androidx.camera:camera-view:1.4.0'
103109

104110
// Coroutines for asynchronous operations
105111
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'

app/src/main/kotlin/com/github/digitallyrefined/androidipcamera/helpers/SecureStorage.kt

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import android.os.Build
55
import android.security.keystore.KeyGenParameterSpec
66
import android.security.keystore.KeyProperties
77
import android.util.Base64
8+
import android.util.Log
89
import androidx.security.crypto.EncryptedSharedPreferences
910
import androidx.security.crypto.MasterKey
11+
import java.io.File
1012
import java.security.KeyStore
1113
import javax.crypto.Cipher
1214
import javax.crypto.KeyGenerator
@@ -16,6 +18,13 @@ import javax.crypto.spec.GCMParameterSpec
1618
class SecureStorage(context: Context) {
1719

1820
private val encryptedPrefs = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
21+
createEncryptedPreferences(context)
22+
} else {
23+
// Fallback for older Android versions
24+
context.getSharedPreferences("secure_prefs", Context.MODE_PRIVATE)
25+
}
26+
27+
private fun createEncryptedPreferences(context: Context) = try {
1928
// Use AndroidX Security library for modern encryption
2029
val masterKey = MasterKey.Builder(context)
2130
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
@@ -28,9 +37,39 @@ class SecureStorage(context: Context) {
2837
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
2938
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
3039
)
31-
} else {
32-
// Fallback for older Android versions
33-
context.getSharedPreferences("secure_prefs", Context.MODE_PRIVATE)
40+
} catch (e: Exception) {
41+
// Handle corrupted encrypted preferences from previous installations
42+
Log.w(TAG, "Failed to open encrypted preferences, attempting to clear corrupted data", e)
43+
44+
// Delete the corrupted encrypted preferences file
45+
val prefsFile = File(context.filesDir.parent, "shared_prefs/secure_prefs.xml")
46+
if (prefsFile.exists()) {
47+
prefsFile.delete()
48+
Log.i(TAG, "Deleted corrupted encrypted preferences file")
49+
}
50+
51+
// Delete the master key if it exists
52+
try {
53+
val keyStore = KeyStore.getInstance("AndroidKeyStore")
54+
keyStore.load(null)
55+
keyStore.deleteEntry(MasterKey.DEFAULT_MASTER_KEY_ALIAS)
56+
Log.i(TAG, "Deleted master key")
57+
} catch (keyDeleteException: Exception) {
58+
Log.w(TAG, "Could not delete master key", keyDeleteException)
59+
}
60+
61+
// Retry creating encrypted preferences with fresh data
62+
val masterKey = MasterKey.Builder(context)
63+
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
64+
.build()
65+
66+
EncryptedSharedPreferences.create(
67+
context,
68+
"secure_prefs",
69+
masterKey,
70+
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
71+
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
72+
)
3473
}
3574

3675
// Store sensitive data securely
@@ -59,6 +98,8 @@ class SecureStorage(context: Context) {
5998
}
6099

61100
companion object {
101+
private const val TAG = "SecureStorage"
102+
62103
// Keys for sensitive data
63104
const val KEY_USERNAME = "secure_username"
64105
const val KEY_PASSWORD = "secure_password"

build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ buildscript {
44
mavenCentral()
55
}
66
dependencies {
7-
classpath("com.android.tools.build:gradle:8.13.2")
8-
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0")
7+
classpath("com.android.tools.build:gradle:9.0.0")
8+
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.2.10")
99
}
1010
}
1111

gradle.properties

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,14 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
88
android.useAndroidX=true
99
kotlin.code.style=official
1010
android.nonTransitiveRClass=true
11+
android.defaults.buildfeatures.resvalues=true
12+
android.sdk.defaultTargetSdkToCompileSdkIfUnset=false
13+
android.enableAppCompileTimeRClass=false
14+
android.usesSdkInManifest.disallowed=false
15+
android.uniquePackageNames=false
16+
android.dependency.useConstraints=true
17+
android.r8.strictFullModeForKeepRules=false
18+
android.r8.optimizedResourceShrinking=false
19+
android.builtInKotlin=false
20+
android.newDsl=false
1121

gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
44
networkTimeout=10000
55
validateDistributionUrl=true
66
zipStoreBase=GRADLE_USER_HOME

0 commit comments

Comments
 (0)