Skip to content

Commit ecbb0ed

Browse files
authored
Merge pull request #547 from Countly/metricprovider_override
Metricprovider override
2 parents 96beb8f + 05b6124 commit ecbb0ed

File tree

7 files changed

+686
-488
lines changed

7 files changed

+686
-488
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
## 26.1.2
22
* Added `CountlyInitProvider` ContentProvider to register activity lifecycle callbacks before `Application.onCreate()`. This ensures the SDK captures the current activity in single-activity frameworks (Flutter, React Native) and apps with deferred initialization.
33
* Added `CountlyConfig.setInitialActivity(Activity)` as an explicit way for wrapper SDKs to provide the host activity during initialization.
4+
* Added a new config option `setMetricProvider(MetricProvider)` to allow overriding default device metrics with custom values.
45

56
## 26.1.1
67
* Added Content feature method `previewContent(String contentId)` (Experimental!).

sdk/src/androidTest/java/ly/count/android/sdk/DeviceInfoTests.java

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ of this software and associated documentation files (the "Software"), to deal
4242
import org.junit.runner.RunWith;
4343

4444
import static org.junit.Assert.assertEquals;
45+
import static org.junit.Assert.assertNotNull;
4546
import static org.mockito.Mockito.mock;
4647
import static org.mockito.Mockito.when;
4748

@@ -296,6 +297,141 @@ public void testGetMetricsWithOverride_2() throws UnsupportedEncodingException,
296297
TestUtils.bothJSONObjEqual(json, calculatedJSON);
297298
}
298299

300+
// MetricProvider override tests
301+
302+
@Test
303+
public void testMetricProviderOverride_fullOverride() {
304+
MockedMetricProvider override = new MockedMetricProvider();
305+
DeviceInfo deviceInfo = new DeviceInfo(override);
306+
307+
assertEquals("A", deviceInfo.mp.getOS());
308+
assertEquals("B", deviceInfo.mp.getOSVersion());
309+
assertEquals("C", deviceInfo.mp.getDevice());
310+
assertEquals("D", deviceInfo.mp.getManufacturer());
311+
assertEquals("E", deviceInfo.mp.getResolution(TestUtils.getContext()));
312+
assertEquals("F", deviceInfo.mp.getDensity(TestUtils.getContext()));
313+
assertEquals("G", deviceInfo.mp.getCarrier(TestUtils.getContext()));
314+
assertEquals("66", deviceInfo.mp.getTimezoneOffset());
315+
assertEquals("H", deviceInfo.mp.getLocale());
316+
assertEquals(Countly.DEFAULT_APP_VERSION, deviceInfo.mp.getAppVersion(TestUtils.getContext()));
317+
assertEquals("J", deviceInfo.mp.getStore(TestUtils.getContext()));
318+
assertEquals("K", deviceInfo.mp.getDeviceType(TestUtils.getContext()));
319+
assertEquals("42", deviceInfo.mp.getTotalRAM());
320+
assertEquals("12", deviceInfo.mp.getRamCurrent(TestUtils.getContext()));
321+
assertEquals("48", deviceInfo.mp.getRamTotal());
322+
assertEquals("N", deviceInfo.mp.getCpu());
323+
assertEquals("O", deviceInfo.mp.getOpenGL(TestUtils.getContext()));
324+
assertEquals("6", deviceInfo.mp.getBatteryLevel(TestUtils.getContext()));
325+
assertEquals("S", deviceInfo.mp.getOrientation(TestUtils.getContext()));
326+
assertEquals("T", deviceInfo.mp.isRooted());
327+
assertEquals("U", deviceInfo.mp.isOnline(TestUtils.getContext()));
328+
assertEquals("V", deviceInfo.mp.isMuted(TestUtils.getContext()));
329+
assertEquals("Z", deviceInfo.mp.hasHinge(TestUtils.getContext()));
330+
assertEquals("88", deviceInfo.mp.getRunningTime());
331+
332+
DiskMetric diskMetric = deviceInfo.mp.getDiskSpaces(TestUtils.getContext());
333+
assertEquals("45", diskMetric.totalMb);
334+
assertEquals("23", diskMetric.usedMb);
335+
}
336+
337+
@Test
338+
public void testMetricProviderOverride_partialOverride() {
339+
MetricProvider partial = new MetricProvider() {
340+
@Override public String getOS() { return "CustomOS"; }
341+
@Override public String getDevice() { return "CustomDevice"; }
342+
};
343+
DeviceInfo deviceInfo = new DeviceInfo(partial);
344+
345+
// overridden values
346+
assertEquals("CustomOS", deviceInfo.mp.getOS());
347+
assertEquals("CustomDevice", deviceInfo.mp.getDevice());
348+
349+
// non-overridden values should fall back to SDK defaults
350+
assertEquals(android.os.Build.VERSION.RELEASE, deviceInfo.mp.getOSVersion());
351+
assertEquals(android.os.Build.MODEL, regularDeviceInfo.mp.getDevice());
352+
assertEquals(android.os.Build.MANUFACTURER, deviceInfo.mp.getManufacturer());
353+
assertNotNull(deviceInfo.mp.getLocale());
354+
assertNotNull(deviceInfo.mp.getTimezoneOffset());
355+
assertNotNull(deviceInfo.mp.getAppVersion(TestUtils.getContext()));
356+
}
357+
358+
@Test
359+
public void testMetricProviderOverride_nullOverride() {
360+
DeviceInfo deviceInfo = new DeviceInfo(null);
361+
362+
// all values should be SDK defaults, no crash
363+
assertEquals("Android", deviceInfo.mp.getOS());
364+
assertEquals(android.os.Build.VERSION.RELEASE, deviceInfo.mp.getOSVersion());
365+
assertEquals(android.os.Build.MODEL, deviceInfo.mp.getDevice());
366+
assertEquals(android.os.Build.MANUFACTURER, deviceInfo.mp.getManufacturer());
367+
assertNotNull(deviceInfo.mp.getLocale());
368+
assertNotNull(deviceInfo.mp.getTimezoneOffset());
369+
}
370+
371+
@Test
372+
public void testMetricProviderOverride_emptyOverride() {
373+
MetricProvider emptyOverride = new MetricProvider() {};
374+
DeviceInfo deviceInfo = new DeviceInfo(emptyOverride);
375+
376+
// empty override should behave same as null override
377+
assertEquals("Android", deviceInfo.mp.getOS());
378+
assertEquals(android.os.Build.VERSION.RELEASE, deviceInfo.mp.getOSVersion());
379+
assertEquals(android.os.Build.MODEL, deviceInfo.mp.getDevice());
380+
assertNotNull(deviceInfo.mp.getLocale());
381+
}
382+
383+
@Test
384+
public void testMetricProviderOverride_diskSpacesOverride() {
385+
MetricProvider diskOverride = new MetricProvider() {
386+
@Override public DiskMetric getDiskSpaces(Context context) {
387+
return new DiskMetric("100", "50");
388+
}
389+
};
390+
DeviceInfo deviceInfo = new DeviceInfo(diskOverride);
391+
392+
DiskMetric diskMetric = deviceInfo.mp.getDiskSpaces(TestUtils.getContext());
393+
assertEquals("100", diskMetric.totalMb);
394+
assertEquals("50", diskMetric.usedMb);
395+
396+
// other metrics should be defaults
397+
assertEquals("Android", deviceInfo.mp.getOS());
398+
}
399+
400+
@Test
401+
public void testMetricProviderOverride_timezoneAndRamOverride() {
402+
MetricProvider override = new MetricProvider() {
403+
@Override public String getTimezoneOffset() { return "120"; }
404+
@Override public String getTotalRAM() { return "8192"; }
405+
@Override public String getRamTotal() { return "8192"; }
406+
@Override public String getRamCurrent(Context context) { return "4096"; }
407+
};
408+
DeviceInfo deviceInfo = new DeviceInfo(override);
409+
410+
assertEquals("120", deviceInfo.mp.getTimezoneOffset());
411+
assertEquals("8192", deviceInfo.mp.getTotalRAM());
412+
assertEquals("8192", deviceInfo.mp.getRamTotal());
413+
assertEquals("4096", deviceInfo.mp.getRamCurrent(TestUtils.getContext()));
414+
}
415+
416+
@Test
417+
public void testMetricProviderOverride_metricsJson() throws UnsupportedEncodingException, JSONException {
418+
MetricProvider partial = new MetricProvider() {
419+
@Override public String getOS() { return "CustomOS"; }
420+
@Override public String getDevice() { return "CustomDevice"; }
421+
@Override public String getManufacturer() { return "CustomMfg"; }
422+
};
423+
DeviceInfo deviceInfo = new DeviceInfo(partial);
424+
425+
String calculatedMetrics = URLDecoder.decode(deviceInfo.getMetrics(TestUtils.getContext(), null, new ModuleLog()), "UTF-8");
426+
JSONObject json = new JSONObject(calculatedMetrics);
427+
428+
assertEquals("CustomOS", json.getString("_os"));
429+
assertEquals("CustomDevice", json.getString("_device"));
430+
assertEquals("CustomMfg", json.getString("_manufacturer"));
431+
// non-overridden should still be present with defaults
432+
assertEquals(android.os.Build.VERSION.RELEASE, json.getString("_os_version"));
433+
}
434+
299435
@Test
300436
public void getAppVersionWithOverride() {
301437
Map<String, String> metricOverride = new HashMap<>();

sdk/src/androidTest/java/ly/count/android/sdk/MockedMetricProvider.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
import android.util.DisplayMetrics;
55
import androidx.annotation.NonNull;
66
import androidx.annotation.Nullable;
7-
import java.util.AbstractMap;
8-
import java.util.Map;
97

108
public class MockedMetricProvider implements MetricProvider {
119

@@ -41,8 +39,8 @@ public MockedMetricProvider() {
4139
return "G";
4240
}
4341

44-
@Override public int getTimezoneOffset() {
45-
return 66;
42+
@Override public String getTimezoneOffset() {
43+
return "66";
4644
}
4745

4846
@Override public String getLocale() {
@@ -61,8 +59,8 @@ public MockedMetricProvider() {
6159
return "K";
6260
}
6361

64-
@Override public long getTotalRAM() {
65-
return 42;
62+
@Override public String getTotalRAM() {
63+
return "42";
6664
}
6765

6866
@Override public String getRamCurrent(Context context) {
@@ -113,7 +111,7 @@ public MockedMetricProvider() {
113111
return new DisplayMetrics();
114112
}
115113

116-
@Override public Map.Entry<String, String> getDiskSpaces(Context context) {
117-
return new AbstractMap.SimpleEntry<>("45", "23");
114+
@Override public DiskMetric getDiskSpaces(Context context) {
115+
return new DiskMetric("45", "23");
118116
}
119117
}

sdk/src/main/java/ly/count/android/sdk/CountlyConfig.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,19 @@ public synchronized CountlyConfig setLoggingEnabled(boolean enabled) {
379379
return this;
380380
}
381381

382+
/**
383+
* Set a custom metric provider to override default device metrics.
384+
* Only the methods you override will replace the SDK defaults.
385+
* Methods that return null will fall back to the SDK's built-in values.
386+
*
387+
* @param metricProvider Your custom MetricProvider implementation
388+
* @return Returns the same config object for convenient linking
389+
*/
390+
public synchronized CountlyConfig setMetricProvider(MetricProvider metricProvider) {
391+
this.metricProviderOverride = metricProvider;
392+
return this;
393+
}
394+
382395
/**
383396
* Call to enable uncaught crash reporting
384397
*

0 commit comments

Comments
 (0)