Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
* `SAFE_AREA` mode: Omits status bar, navigation bar and cutouts when displaying webviews.
* Added a new init config option `disableGradualRequestCleaner()` to change request queue overflow behavior. When enabled, all overflowing requests (plus one slot) are removed at once instead of being cleaned gradually in limited batches.

* Added a new method `requestQueue().addCustomNetworkRequestHeaders(Map<String,String>)` for providing or overriding custom headers after init

* Immediate requests now will be run by parallel executor instead of serial by default.

## 25.4.4
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package ly.count.android.sdk;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.mockito.Mockito.mock;

/**
* Tests for runtime custom header manipulation via Countly.addCustomNetworkRequestHeaders(Map<String,String>)
*/
@RunWith(AndroidJUnit4.class)
public class CustomHeaderRuntimeTests {

Countly mCountly;

@Before
public void setUp() {
final CountlyStore countlyStore = new CountlyStore(TestUtils.getContext(), mock(ModuleLog.class));
countlyStore.clear();

mCountly = new Countly();
mCountly.init(new CountlyConfig(TestUtils.getContext(), "appkey", "http://test.count.ly").setDeviceId("1234").setLoggingEnabled(true));
}

@Test
public void testRuntimeAddAndOverrideHeaders() throws Exception {
// Add initial headers at runtime
Map<String, String> initial = new HashMap<>();
initial.put("X-First", "One");
initial.put("X-Second", "Two");
mCountly.requestQueue().addCustomNetworkRequestHeaders(initial);

// Override one and add a new one
Map<String, String> second = new HashMap<>();
second.put("X-Second", "TwoOverride");
second.put("X-Third", "Three");
mCountly.requestQueue().addCustomNetworkRequestHeaders(second);

ConnectionProcessor cp = new ConnectionProcessor(
"http://test.count.ly",
mCountly.countlyStore,
mCountly.config_.deviceIdProvider,
mCountly.config_.configProvider,
mCountly.connectionQueue_.requestInfoProvider,
null,
mCountly.requestHeaderCustomValues,
mCountly.L,
mCountly.config_.healthTracker,
mock(Runnable.class)
);

URLConnection urlConnection = cp.urlConnectionForServerRequest("a=b", null);

Assert.assertEquals("One", urlConnection.getRequestProperty("X-First"));
Assert.assertEquals("TwoOverride", urlConnection.getRequestProperty("X-Second"));
Assert.assertEquals("Three", urlConnection.getRequestProperty("X-Third"));
}
}
43 changes: 43 additions & 0 deletions sdk/src/main/java/ly/count/android/sdk/Countly.java
Original file line number Diff line number Diff line change
Expand Up @@ -1157,6 +1157,49 @@ public void setLoggingEnabled(final boolean enableLogging) {
L.d("Enabling logging");
}

/**
* To add new header key/value pairs or override existing ones.
* A null or empty map is ignored. Null or empty keys, as well as null values, are ignored.
* Subsequent requests (including those created after overriding) will contain the updated header set.
*
* @param customHeaderValues map of header key/value pairs to add/override
* @return Returns the same Countly instance for convenient chaining
*/
/* package */ synchronized void addCustomNetworkRequestHeaders(Map<String, String> customHeaderValues) {
if (!isInitialized()) {
L.e("[addCustomNetworkRequestHeaders] SDK must be initialised before calling this method");
return;
}

if (customHeaderValues == null || customHeaderValues.isEmpty()) {
L.d("[addCustomNetworkRequestHeaders] Provided map was null or empty, ignoring");
return;
}

if (requestHeaderCustomValues == null) {
requestHeaderCustomValues = new HashMap<>();
}

int added = 0;
int overridden = 0;
for (Map.Entry<String, String> entry : customHeaderValues.entrySet()) {
String k = entry.getKey();
String v = entry.getValue();
if (k == null || k.isEmpty() || v == null) {
continue; // skip invalid entries
}
if (requestHeaderCustomValues.containsKey(k)) {
overridden++;
} else {
added++;
}
requestHeaderCustomValues.put(k, v);
}

connectionQueue_.setRequestHeaderCustomValues(requestHeaderCustomValues);
L.i("[addCustomNetworkRequestHeaders] Added:" + added + " Overridden:" + overridden + " TotalNow:" + requestHeaderCustomValues.size());
}

/**
* Check if logging has been enabled internally in the SDK
*
Expand Down
16 changes: 16 additions & 0 deletions sdk/src/main/java/ly/count/android/sdk/ModuleRequestQueue.java
Original file line number Diff line number Diff line change
Expand Up @@ -456,5 +456,21 @@ public void recordMetrics(@Nullable Map<String, String> metricsOverride) {
recordMetricsInternal(tempMetricsOverride);
}
}

/**
* To add new header key/value pairs or override existing ones.
* A null or empty map is ignored. Null or empty keys, as well as null values,
* are ignored.
* Subsequent requests (including those created after overriding) will contain
* the updated header set.
*
* @param customHeaderValues header key/value pairs to add or override
*/
public void addCustomNetworkRequestHeaders(@Nullable Map<String, String> customHeaderValues) {
synchronized (_cly) {
L.i("[RequestQueue] addCustomNetworkRequestHeaders, Calling addCustomNetworkRequestHeaders");
_cly.addCustomNetworkRequestHeaders(customHeaderValues);
}
}
}
}
Loading