11package io .branch .referral ;
22
3+ import static android .content .Context .UI_MODE_SERVICE ;
4+ import static io .branch .referral .PrefHelper .NO_STRING_VALUE ;
5+
36import android .app .UiModeManager ;
47import android .content .Context ;
58import android .content .res .Configuration ;
6- import android .os .Build ;
7- import android .os .Handler ;
8- import android .os .Looper ;
99import android .text .TextUtils ;
1010import android .util .DisplayMetrics ;
11- import android .util .Log ;
12- import android .webkit .WebSettings ;
13- import android .webkit .WebView ;
11+
12+ import androidx .annotation .NonNull ;
1413
1514import org .json .JSONException ;
1615import org .json .JSONObject ;
1716
18- import static android .content .Context .UI_MODE_SERVICE ;
19- import static io .branch .referral .PrefHelper .NO_STRING_VALUE ;
20-
21- import java .util .Iterator ;
22- import java .util .Objects ;
17+ import io .branch .coroutines .DeviceSignalsKt ;
18+ import kotlin .coroutines .Continuation ;
19+ import kotlin .coroutines .CoroutineContext ;
20+ import kotlin .coroutines .EmptyCoroutineContext ;
2321
2422/**
2523 * <p>
@@ -215,7 +213,8 @@ void updateRequestWithV2Params(ServerRequest serverRequest, PrefHelper prefHelpe
215213 userDataObj .put (Defines .Jsonkey .AppVersion .getKey (), getAppVersion ());
216214 userDataObj .put (Defines .Jsonkey .SDK .getKey (), "android" );
217215 userDataObj .put (Defines .Jsonkey .SdkVersion .getKey (), Branch .getSdkVersionNumber ());
218- userDataObj .put (Defines .Jsonkey .UserAgent .getKey (), getDefaultBrowserAgent (context_ ));
216+
217+ setPostUserAgent (userDataObj );
219218
220219 if (serverRequest instanceof ServerRequestGetLATD ) {
221220 userDataObj .put (Defines .Jsonkey .LATDAttributionWindow .getKey (),
@@ -236,6 +235,86 @@ void updateRequestWithV2Params(ServerRequest serverRequest, PrefHelper prefHelpe
236235 }
237236 }
238237
238+ /**
239+ * Method to append the user agent string to the POST request body's user_data object
240+ * If the user agent string is empty, either because it was not obtained asynchronously
241+ * or on time, query it synchronously.
242+ * @param userDataObj
243+ */
244+ private void setPostUserAgent (final JSONObject userDataObj ) {
245+ BranchLogger .v ("setPostUserAgent " + Thread .currentThread ().getName ());
246+ try {
247+ if (!TextUtils .isEmpty (Branch ._userAgentString )) {
248+ BranchLogger .v ("userAgent was cached: " + Branch ._userAgentString );
249+
250+ userDataObj .put (Defines .Jsonkey .UserAgent .getKey (), Branch ._userAgentString );
251+
252+ Branch .getInstance ().requestQueue_ .unlockProcessWait (ServerRequest .PROCESS_WAIT_LOCK .USER_AGENT_STRING_LOCK );
253+ Branch .getInstance ().requestQueue_ .processNextQueueItem ("setPostUserAgent" );
254+ }
255+ else if (Branch .userAgentSync ) {
256+ // If user agent sync is false, then the async coroutine is executed instead but may not have finished yet.
257+ BranchLogger .v ("Start invoking getUserAgentSync from thread " + Thread .currentThread ().getName ());
258+ DeviceSignalsKt .getUserAgentSync (context_ , new Continuation <String >() {
259+ @ NonNull
260+ @ Override
261+ public CoroutineContext getContext () {
262+ return EmptyCoroutineContext .INSTANCE ;
263+ }
264+
265+ @ Override
266+ public void resumeWith (@ NonNull Object o ) {
267+ if (o != null ) {
268+ Branch ._userAgentString = (String ) o ;
269+ BranchLogger .v ("onUserAgentStringFetchFinished getUserAgentSync resumeWith releasing lock" );
270+
271+ try {
272+ userDataObj .put (Defines .Jsonkey .UserAgent .getKey (), Branch ._userAgentString );
273+ }
274+ catch (JSONException e ) {
275+ BranchLogger .w ("Caught JSONException " + e .getMessage ());
276+ }
277+ }
278+
279+ Branch .getInstance ().requestQueue_ .unlockProcessWait (ServerRequest .PROCESS_WAIT_LOCK .USER_AGENT_STRING_LOCK );
280+ Branch .getInstance ().requestQueue_ .processNextQueueItem ("onUserAgentStringFetchFinished" );
281+ }
282+ });
283+ }
284+ // In cases where v2 events objects are enqueued before an init, this will execute first.
285+ else {
286+ DeviceSignalsKt .getUserAgentAsync (context_ , new Continuation <String >() {
287+ @ NonNull
288+ @ Override
289+ public CoroutineContext getContext () {
290+ return EmptyCoroutineContext .INSTANCE ;
291+ }
292+
293+ @ Override
294+ public void resumeWith (@ NonNull Object o ) {
295+ if (o != null ) {
296+ Branch ._userAgentString = (String ) o ;
297+ BranchLogger .v ("onUserAgentStringFetchFinished getUserAgentAsync resumeWith releasing lock" );
298+
299+ try {
300+ userDataObj .put (Defines .Jsonkey .UserAgent .getKey (), Branch ._userAgentString );
301+ }
302+ catch (JSONException e ) {
303+ BranchLogger .w ("Caught JSONException " + e .getMessage ());
304+ }
305+ }
306+
307+ Branch .getInstance ().requestQueue_ .unlockProcessWait (ServerRequest .PROCESS_WAIT_LOCK .USER_AGENT_STRING_LOCK );
308+ Branch .getInstance ().requestQueue_ .processNextQueueItem ("getUserAgentAsync resumeWith" );
309+ }
310+ });
311+ }
312+ }
313+ catch (Exception exception ){
314+ BranchLogger .w ("Caught exception trying to set userAgent " + exception .getMessage ());
315+ }
316+ }
317+
239318 /**
240319 * get the package name for the this application
241320 *
@@ -288,63 +367,6 @@ public String getOsName() {
288367 return systemObserver_ .getOS (context_ );
289368 }
290369
291-
292- /**
293- * Returns the browser's user agent string
294- * PRS : User agent is checked only from api-17
295- * @param context
296- * @return user agent string
297- */
298- String getDefaultBrowserAgent (final Context context ) {
299- if (!TextUtils .isEmpty (Branch ._userAgentString )) {
300- return Branch ._userAgentString ;
301- }
302-
303- if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .JELLY_BEAN_MR1 ) {
304- try {
305- BranchLogger .v ("Retrieving user agent string from WebSettings" );
306- Branch ._userAgentString = WebSettings .getDefaultUserAgent (context );
307- }
308- catch (Exception exception ) {
309- BranchLogger .v (exception .getMessage ());
310- // A known Android issue. Webview packages are not accessible while any updates for chrome is in progress.
311- // https://bugs.chromium.org/p/chromium/issues/detail?id=506369
312- }
313- }
314- return Branch ._userAgentString ;
315- }
316-
317- /**
318- * Must be called from the main thread
319- * Some devices appear to crash when accessing chromium through the Android framework statics
320- * Suggested alternative is to use a webview instance
321- * https://bugs.chromium.org/p/chromium/issues/detail?id=1279562
322- * https://bugs.chromium.org/p/chromium/issues/detail?id=1271617
323- **/
324- String getUserAgentStringSync (final Context context ){
325- if (!TextUtils .isEmpty (Branch ._userAgentString )) {
326- return Branch ._userAgentString ;
327- }
328-
329- new Handler (Looper .getMainLooper ()).post (new Runnable () {
330- @ Override
331- public void run () {
332- try {
333- BranchLogger .v ("Running WebView initialization for user agent on thread " + Thread .currentThread ());
334- WebView w = new WebView (context );
335- Branch ._userAgentString = w .getSettings ().getUserAgentString ();
336- w .destroy ();
337- }
338- catch (Exception e ) {
339- BranchLogger .v (e .getMessage ());
340- }
341-
342- }
343- });
344-
345- return Branch ._userAgentString ;
346- }
347-
348370 /**
349371 * Concrete SystemObserver implementation
350372 */
@@ -364,6 +386,4 @@ SystemObserver getSystemObserver() {
364386 public static boolean isNullOrEmptyOrBlank (String str ) {
365387 return TextUtils .isEmpty (str ) || str .equals (SystemObserver .BLANK );
366388 }
367-
368-
369389}
0 commit comments