Skip to content

Commit 97f5a6c

Browse files
authored
Merge pull request #786 from Iterable/jwt/SDK-196-android-retryinterval-not-respected-always-def
[SDK-196] Fix retryInterval not being able to be updated
2 parents e75b775 + 1a6d487 commit 97f5a6c

File tree

3 files changed

+90
-8
lines changed

3 files changed

+90
-8
lines changed

CHANGELOG.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
## 2.2.0-alpha.2
2+
3+
### Updates
4+
* Changed `onJWTError` to `onJwtError`
5+
* Changed `IterableRetryBackoff` enum keys to be lowercase for consistency
6+
across application
7+
8+
### Fixes
9+
* Fixed Android `retryInterval` not being updated on re-initialization.
10+
111
## 2.2.0-alpha.1
212

313
### Updates
@@ -6,7 +16,6 @@
616
### Fixes
717
* [SDK-151] Fixed "cannot read property authtoken of undefined" error
818

9-
1019
## 2.2.0-alpha.0
1120

1221
### Updates

android/src/main/java/com/iterable/reactnative/RNIterableAPIModuleImpl.java

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.iterable.iterableapi.IterableActionContext;
2525
import com.iterable.iterableapi.IterableApi;
2626
import com.iterable.iterableapi.IterableAuthHandler;
27+
import com.iterable.iterableapi.IterableAuthManager;
2728
import com.iterable.iterableapi.IterableConfig;
2829
import com.iterable.iterableapi.IterableCustomActionHandler;
2930
import com.iterable.iterableapi.IterableAttributionInfo;
@@ -88,7 +89,36 @@ public void initializeWithApiKey(String apiKey, ReadableMap configReadableMap, S
8889
configBuilder.setAuthHandler(this);
8990
}
9091

91-
IterableApi.initialize(reactContext, apiKey, configBuilder.build());
92+
IterableConfig config = configBuilder.build();
93+
IterableApi.initialize(reactContext, apiKey, config);
94+
95+
// Update retry policy on existing authManager if it was already created
96+
// This fixes the issue where retryInterval is not respected after
97+
// re-initialization
98+
// TODO [SDK-197]: Fix the root cause of this issue, instead of this hack
99+
try {
100+
// Use reflection to access package-private fields and methods
101+
java.lang.reflect.Field configRetryPolicyField = config.getClass().getDeclaredField("retryPolicy");
102+
configRetryPolicyField.setAccessible(true);
103+
Object retryPolicy = configRetryPolicyField.get(config);
104+
105+
if (retryPolicy != null) {
106+
java.lang.reflect.Method getAuthManagerMethod = IterableApi.getInstance().getClass().getDeclaredMethod("getAuthManager");
107+
getAuthManagerMethod.setAccessible(true);
108+
IterableAuthManager authManager = (IterableAuthManager) getAuthManagerMethod.invoke(IterableApi.getInstance());
109+
110+
if (authManager != null) {
111+
// Update the retry policy field on the authManager
112+
java.lang.reflect.Field authRetryPolicyField = authManager.getClass().getDeclaredField("authRetryPolicy");
113+
authRetryPolicyField.setAccessible(true);
114+
authRetryPolicyField.set(authManager, retryPolicy);
115+
IterableLogger.d(TAG, "Updated retry policy on existing authManager");
116+
}
117+
}
118+
} catch (Exception e) {
119+
IterableLogger.e(TAG, "Failed to update retry policy: " + e.getMessage());
120+
}
121+
92122
IterableApi.getInstance().setDeviceAttribute("reactNativeSDKVersion", version);
93123

94124
IterableApi.getInstance().getInAppManager().addListener(this);
@@ -122,7 +152,36 @@ public void initialize2WithApiKey(String apiKey, ReadableMap configReadableMap,
122152
// override in the Android SDK. Check with @Ayyanchira and @evantk91 to
123153
// see what the best approach is.
124154

125-
IterableApi.initialize(reactContext, apiKey, configBuilder.build());
155+
IterableConfig config = configBuilder.build();
156+
IterableApi.initialize(reactContext, apiKey, config);
157+
158+
// Update retry policy on existing authManager if it was already created
159+
// This fixes the issue where retryInterval is not respected after
160+
// re-initialization
161+
// TODO [SDK-197]: Fix the root cause of this issue, instead of this hack
162+
try {
163+
// Use reflection to access package-private fields and methods
164+
java.lang.reflect.Field configRetryPolicyField = config.getClass().getDeclaredField("retryPolicy");
165+
configRetryPolicyField.setAccessible(true);
166+
Object retryPolicy = configRetryPolicyField.get(config);
167+
168+
if (retryPolicy != null) {
169+
java.lang.reflect.Method getAuthManagerMethod = IterableApi.getInstance().getClass().getDeclaredMethod("getAuthManager");
170+
getAuthManagerMethod.setAccessible(true);
171+
IterableAuthManager authManager = (IterableAuthManager) getAuthManagerMethod.invoke(IterableApi.getInstance());
172+
173+
if (authManager != null) {
174+
// Update the retry policy field on the authManager
175+
java.lang.reflect.Field authRetryPolicyField = authManager.getClass().getDeclaredField("authRetryPolicy");
176+
authRetryPolicyField.setAccessible(true);
177+
authRetryPolicyField.set(authManager, retryPolicy);
178+
IterableLogger.d(TAG, "Updated retry policy on existing authManager");
179+
}
180+
}
181+
} catch (Exception e) {
182+
IterableLogger.e(TAG, "Failed to update retry policy: " + e.getMessage());
183+
}
184+
126185
IterableApi.getInstance().setDeviceAttribute("reactNativeSDKVersion", version);
127186

128187
IterableApi.getInstance().getInAppManager().addListener(this);

example/src/hooks/useIterableApp.tsx

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
8989

9090
const getIsEmail = (id: string) => EMAIL_REGEX.test(id);
9191

92+
let lastTimeStamp = 0;
93+
9294
export const IterableAppProvider: FunctionComponent<
9395
React.PropsWithChildren<unknown>
9496
> = ({ children }) => {
@@ -141,17 +143,15 @@ export const IterableAppProvider: FunctionComponent<
141143

142144
const initialize = useCallback(
143145
(navigation: Navigation) => {
144-
if (getUserId()) {
145-
login();
146-
}
146+
logout();
147147

148148
const config = new IterableConfig();
149149

150150
config.inAppDisplayInterval = 1.0; // Min gap between in-apps. No need to set this in production.
151151

152152
config.retryPolicy = {
153153
maxRetry: 5,
154-
retryInterval: 10,
154+
retryInterval: 5,
155155
retryBackoff: IterableRetryBackoff.linear,
156156
};
157157

@@ -199,8 +199,16 @@ export const IterableAppProvider: FunctionComponent<
199199
process.env.ITBL_JWT_SECRET
200200
) {
201201
config.authHandler = async () => {
202+
console.group('authHandler');
203+
const now = Date.now();
204+
if (lastTimeStamp !== 0) {
205+
console.log('Time since last call:', now - lastTimeStamp);
206+
}
207+
lastTimeStamp = now;
208+
console.groupEnd();
209+
210+
// return 'InvalidToken'; // Uncomment this to test the failure callback
202211
const token = await getJwtToken();
203-
// return 'SomethingNotValid'; // Uncomment this to test the failure callback
204212
return token;
205213
};
206214
}
@@ -219,6 +227,10 @@ export const IterableAppProvider: FunctionComponent<
219227
.then((isSuccessful) => {
220228
setIsInitialized(isSuccessful);
221229

230+
if (isSuccessful && getUserId()) {
231+
return login();
232+
}
233+
222234
if (!isSuccessful) {
223235
return Promise.reject('`Iterable.initialize` failed');
224236
}
@@ -242,6 +254,8 @@ export const IterableAppProvider: FunctionComponent<
242254
const logout = useCallback(() => {
243255
Iterable.setEmail(null);
244256
Iterable.setUserId(null);
257+
Iterable.logout();
258+
lastTimeStamp = 0;
245259
setIsLoggedIn(false);
246260
}, []);
247261

0 commit comments

Comments
 (0)