App: [HOLD for payment 2023-05-03] [$1000] [Crash] Investigate EventEmitter.addEvent on Android
Problem
in version 1.2.99-6 we are running into this error on Android, on mostly Sony devices related to the urban airship
Fatal Exception: java.lang.NoSuchMethodError: No interface method putIfAbsent(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; in class Ljava/util/Map; or its super classes (declaration of 'java.util.Map' appears in /system/framework/core-libart.jar)
at com.urbanairship.android.framework.proxy.events.EventEmitter.addEvent(EventEmitter.kt:32)
at com.urbanairship.android.framework.proxy.AirshipListener.onInboxUpdated(AirshipListener.kt:123)
at com.urbanairship.messagecenter.Inbox$9.run(Inbox.java:763)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:211)
at android.app.ActivityThread.main(ActivityThread.java:5371)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:945)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:740)
Why is it important
Its causing app to crash
solution
Investigate and try to fix this crash
Upwork Automation - Do Not Edit
- Upwork Job URL: https://www.upwork.com/jobs/~01ef230aad8534b92a
- Upwork Job ID: 1648082798749863936
- Last Price Increase: 2023-04-17
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 38 (24 by maintainers)
@akinwale I am updating the code to remove putIfAbsent so it will be backwards compatible.
We cant just do a simple put since the code is tracking pending events that the plugin is unable to send yet (no listener). The list is needed since we might have multiple events of the same type. Your proposal of doing a check for null first would of worked, but since we are in Kotlin I used a handy
getOrPutmethod. Here is the change - https://github.com/urbanairship/airship-mobile-framework-proxy/pull/7/filesI will have a fix out today, so I think the path forward is to just wait for the release and update to resolve this issue.
Oh wait, you already did. Okay, cool. I’m just a money man. 😄
Paid!
Offer resent to the correct profile!
Sorry paid @akinwale. Offer sent to @rushatgabhane: https://www.upwork.com/nx/wm/pre-hire/c/8577561/offer/24422081
Thanks for the bump @akinwale. Looks like this was unblocked for payment yesterday.
@twisterdotcom @rushatgabhane I checked off all the regression items because the regression occurred on an external library.
Thanks for the speedy update Ryan!
Okay, @akinwale would you like to update your proposal to simply update the library?
Airship 15.2.3 release is out
Thanks for the report, ill get this resolved this week.
Yes. From line 32 of the EventEmitter class.
Proposal
Please re-state the problem that we are trying to solve in this issue.
There is an app crash on mostly Sony devices related to urban airship.
What is the root cause of that problem?
The source of the problem is the
putIfAbsentmethod being called by theairship-mobile-frameworkpackage.https://github.com/urbanairship/airship-mobile-framework-proxy/blob/3e9cf017e4b878f21afccaf103658e9b882dc13f/android/airship-framework-proxy/src/main/java/com/urbanairship/android/framework/proxy/events/EventEmitter.kt#L32
The
putIfAbsentmethod was introduced in API Level 24 (Android 7) according to the documentation forjava.util.Mapwhich is the base interface for maps. Trying to execute this on a device which is running a version of Android prior to 7 will result in this error. Thus, it makes sense that mostly Sony devices would be affected they haven’t been diligent with major Android software updates. To verify, check the crash version being reported by Firebase.What changes do you think we should make in order to solve the problem?
Update: With the release of react-native-airship 15.2.3 which incorporates a fix for the problem, we can simply update
package.jsonwith the new version number.https://github.com/Expensify/App/blob/f54a8bd23018644d33114d1820f7e428f18c74f9/package.json#L67
We can either propose a change upstream to fix the issue. Changing the
putIfAbsentcall to justputshould be adequate, since it’s simply adding a key/value pair to a map, and if the key already exists, it will be overwritten. If it’s absolutely necessary to check that the key exists, then we can use a combination of a!containsKeyorget(key) == nullcheck, and if the key doesn’t exist or the key value is null, use theputmethod to add the key/value pair to the map.Alternatively, if the change cannot be applied upstream, maintain a fork of the
airship-mobile-framework-proxypackage. This is a dependency for thereact-native-airshippackage, so a fork of this would have to be maintained as well.https://github.com/urbanairship/react-native-airship/blob/main/android/build.gradle#L153
What alternative solutions did you explore? (Optional)
This would be more restrictive, but it’s possible to set 24 as the
minSdkVersionfor Android builds. This would prevent the app from being installed on devices running older versions of Android.