Skip to content

Commit 5ec76ab

Browse files
committed
migrate away from deprecated crypto lib
1 parent ebc0f96 commit 5ec76ab

File tree

7 files changed

+362
-20
lines changed

7 files changed

+362
-20
lines changed

app/build.gradle.kts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ android {
5454
argument("room.schemaLocation", "$projectDir/schemas")
5555
}
5656
}
57+
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
5758
}
5859
signingConfigs {
5960
register("release") {
@@ -138,6 +139,7 @@ play {
138139
}
139140

140141
dependencies {
142+
val assertJVersion = "3.27.3"
141143
val roomVersion = "2.7.1"
142144

143145
implementation("androidx.appcompat:appcompat:1.7.0")
@@ -146,6 +148,7 @@ dependencies {
146148
implementation("androidx.preference:preference:1.2.1")
147149
implementation("androidx.room:room-guava:$roomVersion")
148150
implementation("androidx.room:room-runtime:$roomVersion")
151+
// deprecated, but we need to keep it another version for migration
149152
implementation("androidx.security:security-crypto:1.1.0-alpha07")
150153
implementation("androidx.viewpager2:viewpager2:1.1.0")
151154
implementation("androidx.work:work-runtime:2.10.1")
@@ -154,8 +157,10 @@ dependencies {
154157
implementation("org.altbeacon:android-beacon-library:2.21.1")
155158
implementation("org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5")
156159
testImplementation("junit:junit:4.13.2")
157-
testImplementation("org.assertj:assertj-core:3.27.3")
160+
testImplementation("org.assertj:assertj-core:$assertJVersion")
158161
testImplementation("org.mockito:mockito-inline:5.2.0")
162+
androidTestImplementation("androidx.test:runner:1.6.2")
163+
androidTestImplementation("org.assertj:assertj-core:$assertJVersion")
159164

160165
annotationProcessor("androidx.room:room-compiler:$roomVersion")
161166

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
package org.ostrya.presencepublisher.device;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
5+
import android.content.SharedPreferences;
6+
7+
import androidx.annotation.Nullable;
8+
9+
import org.junit.Test;
10+
11+
import java.util.HashMap;
12+
import java.util.Map;
13+
import java.util.Optional;
14+
import java.util.Set;
15+
16+
public class DevicePreferenceTest {
17+
@Test
18+
public void cryptoWorks() {
19+
SharedPreferences delegate = new InMemoryPreferences();
20+
DevicePreferences uut = new DevicePreferences(delegate);
21+
22+
uut.putString("key", "value");
23+
assertThat(uut.getString("key", "default")).isEqualTo("value");
24+
assertThat(delegate.getString("key", "default"))
25+
.isNotEqualTo("default")
26+
.isNotEqualTo("value");
27+
}
28+
29+
private static class InMemoryPreferences implements SharedPreferences {
30+
private final Map<String, Object> entries = new HashMap<>();
31+
32+
@Override
33+
public Map<String, ?> getAll() {
34+
return entries;
35+
}
36+
37+
@Nullable
38+
@Override
39+
public String getString(String key, @Nullable String defValue) {
40+
return Optional.ofNullable(entries.getOrDefault(key, null))
41+
.filter(String.class::isInstance)
42+
.map(String.class::cast)
43+
.orElse(defValue);
44+
}
45+
46+
@Nullable
47+
@Override
48+
public Set<String> getStringSet(String key, @Nullable Set<String> defValues) {
49+
return Optional.ofNullable(entries.getOrDefault(key, null))
50+
.filter(Set.class::isInstance)
51+
.map(Set.class::cast)
52+
.orElse(defValues);
53+
}
54+
55+
@Override
56+
public int getInt(String key, int defValue) {
57+
return Optional.ofNullable(entries.getOrDefault(key, null))
58+
.filter(Integer.class::isInstance)
59+
.map(Integer.class::cast)
60+
.orElse(defValue);
61+
}
62+
63+
@Override
64+
public long getLong(String key, long defValue) {
65+
return Optional.ofNullable(entries.getOrDefault(key, null))
66+
.filter(Long.class::isInstance)
67+
.map(Long.class::cast)
68+
.orElse(defValue);
69+
}
70+
71+
@Override
72+
public float getFloat(String key, float defValue) {
73+
return Optional.ofNullable(entries.getOrDefault(key, null))
74+
.filter(Float.class::isInstance)
75+
.map(Float.class::cast)
76+
.orElse(defValue);
77+
}
78+
79+
@Override
80+
public boolean getBoolean(String key, boolean defValue) {
81+
return Optional.ofNullable(entries.getOrDefault(key, null))
82+
.filter(Boolean.class::isInstance)
83+
.map(Boolean.class::cast)
84+
.orElse(defValue);
85+
}
86+
87+
@Override
88+
public boolean contains(String key) {
89+
return entries.containsKey(key);
90+
}
91+
92+
@Override
93+
public Editor edit() {
94+
return new Editor() {
95+
@Override
96+
public Editor putString(String key, @Nullable String value) {
97+
entries.put(key, value);
98+
return this;
99+
}
100+
101+
@Override
102+
public Editor putStringSet(String key, @Nullable Set<String> values) {
103+
entries.put(key, values);
104+
return this;
105+
}
106+
107+
@Override
108+
public Editor putInt(String key, int value) {
109+
entries.put(key, value);
110+
return this;
111+
}
112+
113+
@Override
114+
public Editor putLong(String key, long value) {
115+
entries.put(key, value);
116+
return this;
117+
}
118+
119+
@Override
120+
public Editor putFloat(String key, float value) {
121+
entries.put(key, value);
122+
return this;
123+
}
124+
125+
@Override
126+
public Editor putBoolean(String key, boolean value) {
127+
entries.put(key, value);
128+
return this;
129+
}
130+
131+
@Override
132+
public Editor remove(String key) {
133+
entries.remove(key);
134+
return this;
135+
}
136+
137+
@Override
138+
public Editor clear() {
139+
entries.clear();
140+
return this;
141+
}
142+
143+
@Override
144+
public boolean commit() {
145+
return true;
146+
}
147+
148+
@Override
149+
public void apply() {}
150+
};
151+
}
152+
153+
@Override
154+
public void registerOnSharedPreferenceChangeListener(
155+
OnSharedPreferenceChangeListener listener) {}
156+
157+
@Override
158+
public void unregisterOnSharedPreferenceChangeListener(
159+
OnSharedPreferenceChangeListener listener) {}
160+
}
161+
}

app/src/main/java/org/ostrya/presencepublisher/PresencePublisher.java

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import static org.ostrya.presencepublisher.preference.about.LocationConsentPreference.LOCATION_CONSENT;
44
import static org.ostrya.presencepublisher.preference.condition.BeaconCategorySupport.BEACON_LIST;
5+
import static org.ostrya.presencepublisher.preference.connection.PasswordPreference.PASSWORD;
56

67
import android.content.SharedPreferences;
78
import android.content.pm.PackageManager;
@@ -20,6 +21,7 @@
2021
import org.altbeacon.beacon.Settings;
2122
import org.altbeacon.beacon.logging.LogManager;
2223
import org.eclipse.paho.client.mqttv3.logging.LoggerFactory;
24+
import org.ostrya.presencepublisher.device.DevicePreferences;
2325
import org.ostrya.presencepublisher.log.BeaconLoggerAdapter;
2426
import org.ostrya.presencepublisher.log.DatabaseLogger;
2527
import org.ostrya.presencepublisher.log.LogUncaughtExceptionHandler;
@@ -28,6 +30,7 @@
2830
import org.ostrya.presencepublisher.mqtt.context.condition.network.NetworkService;
2931
import org.ostrya.presencepublisher.notification.NotificationFactory;
3032
import org.ostrya.presencepublisher.preference.about.NightModePreference;
33+
import org.ostrya.presencepublisher.preference.connection.PasswordPreference;
3134

3235
import java.util.Collections;
3336
import java.util.List;
@@ -43,9 +46,6 @@ public class PresencePublisher extends MultiDexApplication {
4346

4447
public static final String MQTT_CLIENT_ID = "mqttClientId";
4548

46-
private static final String USE_WORKER_1 = "useWorker1";
47-
private static final String CURRENT_WIFI_SSID = "currentWifiSsid";
48-
4949
private final AtomicReference<ConnectivityManager.NetworkCallback> currentCallback =
5050
new AtomicReference<>();
5151

@@ -59,10 +59,10 @@ public void onCreate() {
5959
setUpConditionCallbacks(preferences);
6060
}
6161
new NotificationFactory(this).createNotificationChannels();
62-
initClientId(preferences);
62+
migratePreferences(preferences);
63+
initClientId();
6364
NightModePreference.updateCurrentNightMode(preferences);
6465
DynamicColors.applyToActivitiesIfAvailable(this);
65-
removeOldValues(preferences);
6666
}
6767

6868
public void setUpConditionCallbacks(SharedPreferences preferences) {
@@ -144,10 +144,11 @@ private void initBeaconCallback(SharedPreferences preferences) {
144144
}
145145
}
146146

147-
private void initClientId(SharedPreferences preferences) {
148-
if (!preferences.contains(MQTT_CLIENT_ID)) {
147+
private void initClientId() {
148+
DevicePreferences devicePreferences = new DevicePreferences(this);
149+
if (!devicePreferences.contains(MQTT_CLIENT_ID)) {
149150
DatabaseLogger.i(TAG, "Generating persistent client ID");
150-
preferences.edit().putString(MQTT_CLIENT_ID, UUID.randomUUID().toString()).apply();
151+
devicePreferences.putString(MQTT_CLIENT_ID, UUID.randomUUID().toString());
151152
}
152153
}
153154

@@ -174,7 +175,16 @@ public boolean supportsBeacons() {
174175
return getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);
175176
}
176177

177-
private void removeOldValues(SharedPreferences preferences) {
178-
preferences.edit().remove(USE_WORKER_1).remove(CURRENT_WIFI_SSID).apply();
178+
private void migratePreferences(SharedPreferences preferences) {
179+
DevicePreferences devicePreferences = new DevicePreferences(this);
180+
String value = PasswordPreference.getOldPasswordProvider(this).get();
181+
if (!devicePreferences.contains(PASSWORD) && value != null) {
182+
devicePreferences.putString(PASSWORD, value);
183+
}
184+
value = preferences.getString(MQTT_CLIENT_ID, null);
185+
if (!devicePreferences.contains(MQTT_CLIENT_ID) && value != null) {
186+
devicePreferences.putString(MQTT_CLIENT_ID, value);
187+
}
188+
preferences.edit().remove(PASSWORD).remove(MQTT_CLIENT_ID).apply();
179189
}
180190
}

0 commit comments

Comments
 (0)