BranchMetrics / android-branch-deep-linking-attribution

The Branch Android SDK for deep linking and attribution. Branch helps mobile apps grow with deep links / deeplinks that power paid acquisition and re-engagement campaigns, referral programs, content sharing, deep linked emails, smart banners, custom user onboarding, and more.
https://docs.branch.io/pages/apps/android/
MIT License
396 stars 156 forks source link

Crash ConcurrentModificationException from Branch #1054

Open JackRam99 opened 1 year ago

JackRam99 commented 1 year ago

Describe the bug

We have gotten around ~300 crashes with the following stack trace.

Exception java.lang.RuntimeException: Unable to resume activity {com.superbalist.android/com.superbalist.android.view.onboarding.OnboardingActivity}: java.util.ConcurrentModificationException
  at android.app.ActivityThread.performResumeActivity (ActivityThread.java:4854)
  at android.app.ActivityThread.handleResumeActivity (ActivityThread.java:4891)
  at android.app.servertransaction.ResumeActivityItem.execute (ResumeActivityItem.java:52)
  at android.app.servertransaction.TransactionExecutor.executeLifecycleState (TransactionExecutor.java:176)
  at android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:97)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2290)
  at android.os.Handler.dispatchMessage (Handler.java:106)
  at android.os.Looper.loop (Looper.java:246)
  at android.app.ActivityThread.main (ActivityThread.java:8469)
  at java.lang.reflect.Method.invoke
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:596)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1130)
Caused by java.util.ConcurrentModificationException:
  at android.util.ArrayMap.put (ArrayMap.java:620)
  at android.os.BaseBundle.putBoolean (BaseBundle.java:611)
  at android.content.Intent.putExtra (Intent.java:9813)
  at io.branch.referral.Branch.extractAppLink (Branch.java:2908)
  at io.branch.referral.Branch.readAndStripParam (Branch.java:1006)
  at io.branch.referral.Branch.onIntentReady (Branch.java:2013)
  at io.branch.referral.BranchActivityLifecycleObserver.onActivityResumed (BranchActivityLifecycleObserver.java:65)
  at android.app.Application.dispatchActivityResumed (Application.java:455)
  at android.app.Activity.dispatchActivityResumed (Activity.java:1412)
  at android.app.Activity.onResume (Activity.java:1944)
  at androidx.fragment.app.FragmentActivity.onResume (FragmentActivity.java:434)
  at com.superbalist.android.view.base.BaseActivityMain.onResume (BaseActivityMain.java:218)
  at com.superbalist.android.view.onboarding.OnboardingActivity.onResume (OnboardingActivity.java:114)
  at android.app.Instrumentation.callActivityOnResume (Instrumentation.java:1456)
  at android.app.Activity.performResume (Activity.java:8332)
  at android.app.ActivityThread.performResumeActivity (ActivityThread.java:4844)

SDK Version

5.2.7

Make and Model

Multiple Devices

OS

8.0, 10, 11, 12, 13

BhagatRohan commented 1 year ago

Facing the same issue in our app after updating from 5.0.1 to 5.2.7 @JackRam99 Have you used "intent?.putExtra("branch_force_new_session", true)" in your code?

JackRam99 commented 1 year ago

Have you used "intent?.putExtra("branch_force_new_session", true)" in your code? @BhagatRohan No ,I did not use it.

catsoft commented 10 months ago

Having the same

Also, this is a duplicate of 900 issue

Can you make it a bit more priority cause apparently it's 20-25% of crashes right now? and not only me according to the task

catsoft commented 10 months ago
private void extractAppLink(Uri data, Activity activity) {
    // ***
    // Save a state in the intent instance
    Intent intent = new Intent(this, AnotherActivity.class);
    intent.putExtra(Defines.IntentKeys.BranchLinkUsed.getKey(), true);
    activity.setIntent(intent);
}

The issue is that you are trying to save a state in an Intent instance, which is not recommended. Consider using SharedPreferences or in-memory storage for such cases. Or, at least, you can copy the intent and do modifications. It appears that your library is attempting to save this state to the intent, which can be read by other code at a later moment.

Here's a small example:

Intent intent = new Intent(this, AnotherActivity.class);
intent.putExtra("key", "value");
startActivity(intent);
// Do not modify `intent.putExtra` here - it may lead to a `ConcurrentModificationException`.
In the example, it's advised not to modify intent.putExtra after calling startActivity to avoid potential issues like a ConcurrentModificationException.

Hope you'll include this fix to your lib in the next release

gdeluna-branch commented 10 months ago

Good catch @catsoft , we'll take a look at your recommendations and see if we can get this in the next sprint.

smoralb commented 9 months ago

Have you guys found a solution to this? We are experiencing a lot of crashes because of this issue.

GoodSir42 commented 6 months ago

We are also experiencing this issue in our app and it produces 40% of our overall crashes. It would be great to hear about progress on this

GoodSir42 commented 3 months ago

This is still a problem. it would help a lot if you could at least catch the issue in your code. Since the initialization is asynchronous we cannot catch it in the surrounding code