Nativescript: Crashes when navigating fast between tabs

Created on 20 Aug 2018  ยท  8Comments  ยท  Source: NativeScript/NativeScript

Please consider this sample:
https://play.nativescript.org/?template=play-js&id=3gxfjn&v=2

If you navigate between tabs fast enough you run into this problem:

An uncaught Exception occurred on "main" thread.
android.content.res.Resources$NotFoundException: Resource ID #0xffffffec
    at android.content.res.ResourcesImpl.getValue(ResourcesImpl.java:215)
    at android.content.res.Resources.loadXmlResourceParser(Resources.java:2134)
    at android.content.res.Resources.getAnimation(Resources.java:1167)
    at android.animation.AnimatorInflater.loadAnimator(AnimatorInflater.java:125)
    at android.animation.AnimatorInflater.loadAnimator(AnimatorInflater.java:106)
    at android.animation.AnimatorInflater.loadAnimator(AnimatorInflater.java:91)
    at android.app.FragmentManagerImpl.loadAnimator(FragmentManager.java:1089)
    at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1368)
    at android.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1557)
    at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1630)
    at android.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2196)
    at android.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2142)
    at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2043)
    at android.app.FragmentManagerImpl$1.run(FragmentManager.java:719)
    at android.os.Handler.handleCallback(Handler.java:790)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6753)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:482)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

And consider this one: https://play.nativescript.org/?template=play-js&id=3gxfjn&v=3

If you navigate fast between tabs, then you run into this crash:

An uncaught Exception occurred on "main" thread.
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
    at android.view.ViewGroup.addViewInner(ViewGroup.java:4941)
    at android.view.ViewGroup.addView(ViewGroup.java:4772)
    at android.view.ViewGroup.addView(ViewGroup.java:4712)
    at android.view.ViewGroup.addView(ViewGroup.java:4685)
    at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1284)
    at android.app.FragmentManagerImpl.addAddedFragments(FragmentManager.java:2407)
    at android.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2186)
    at android.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2142)
    at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2043)
    at android.app.FragmentManagerImpl$1.run(FragmentManager.java:719)
    at android.os.Handler.handleCallback(Handler.java:790)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6753)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:482)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
backlog android high

Most helpful comment

After spending several more hours playing with the first demo; I can tell you this line of code causes the issue:
https://github.com/NativeScript/NativeScript/blob/master/tns-core-modules/ui/frame/fragment.transitions.android.ts#L153

If I comment out the issue; the crash is gone. Now the reason it runs this line is a bit weird. It seems the state gets messed up somehow.

Here is the log:

*********************************************************************
*** Notes:

    Frame Navigate is the call from the App; to switch the navigation; it output what is supposed to be navigated too next.
    +NavCore = Frame.prototype._navigateCore (frame.android it outputs the newEntry.entry and then currentEntry.entry)

    Name after: (xxxx) - this is the name of the animation choosen in the _setAndroidFragmentTransitions.    It is always "default" when it crashes because the currentEntry is null.

    !!! Fragment.transitions setCustomAnimations (Next to the crashing line, so I know if we hit this path)
     _ProcessNextNavigationEntry - this is the path where it sets _currentEntry to Null

     Fragment onFragmentCreateAnimator ( one of the locations that uses the newAnim value passed in, last one before a crash)
*********************************************************************


+ NavCore {
  "moduleName": "home/home-page"
} Old: NULL -1 -1
+ _setAndroidFragmentTransitions
Name after default
!!! fragment.transitions setCustomAnimations default Diff: false
+ Fragment onFragmentCreateAnimator: enter -10


+ NavCore {
  "moduleName": "home/home-tab/home-tab-page"
} Old: NULL 0 0
+ _setAndroidFragmentTransitions
Name after default
!!! fragment.transitions setCustomAnimations default Diff: false
+ Fragment onFragmentCreateAnimator: enter -10



Frame Navigate:  home/about-tab/about-tab-page slide
+ NavCore {
  "moduleName": "home/about-tab/about-tab-page",
} Old: {
  "moduleName": "home/home-tab/home-tab-page"
} 1 1
+ _setAndroidFragmentTransitions slide
Name after slide
+ Fragment onFragmentCreateAnimator: enter 0
+ Fragment onFragmentCreateAnimator: enter 0



Frame Navigate:  home/contact-tab/contact-tab-page slide
+ NavCore {
  "moduleName": "home/contact-tab/contact-tab-page",
} Old: {
  "moduleName": "home/about-tab/about-tab-page",
} 2 2
+ _setAndroidFragmentTransitions slide
Name after slide
- _setAndroidFragmentTransitions
+ Fragment onFragmentCreateAnimator: enter 0
+ Fragment onFragmentCreateAnimator: enter 0



Frame Navigate:  home/profile-tab/profile-tab-page slide
+ NavCore {
  "moduleName": "home/profile-tab/profile-tab-page",
} Old: {
  "moduleName": "home/contact-tab/contact-tab-page",
} 3 3
+ _setAndroidFragmentTransitions slide
Name after slide
+ Fragment onFragmentCreateAnimator: enter 0
+ Fragment onFragmentCreateAnimator: enter 0



...  (Even more entries deleted between id's 4 to 7 that succeeded) ...



Frame Navigate:  home/about-tab/about-tab-page slideRight
+ NavCore {
  "moduleName": "home/about-tab/about-tab-page",
} Old: {
  "moduleName": "home/contact-tab/contact-tab-page",
} 7 7
+ _setAndroidFragmentTransitions slideRight
Name after slideright
+ Fragment onFragmentCreateAnimator: enter 0
+ Fragment onFragmentCreateAnimator: enter 0


Frame Navigate:  home/home-tab/home-tab-page slideRight
+ NavCore {
  "moduleName": "home/home-tab/home-tab-page",
} Old: {
  "moduleName": "home/about-tab/about-tab-page",
} 8 8
+ _setAndroidFragmentTransitions slideRight
Name after slideright
+ Fragment onFragmentCreateAnimator: enter 0
+ Fragment onFragmentCreateAnimator: enter 0


******************************************************************************
** Here is where the log changes drastically and goes into the crash state...
******************************************************************************

Frame Navigate:  home/contact-tab/contact-tab-page slide
_ProcessNextNavigationEntry _currentEntry=null fragment8[8]
+ NavCore {
  "moduleName": "home/about-tab/about-tab-page",
} Old: NULL 9 9
+ _setAndroidFragmentTransitions
Name after default
!!! fragment.transitions setCustomAnimations default Diff: false
- _setAndroidFragmentTransitions
+ Fragment onFragmentCreateAnimator: enter -20

System.err: android.content.res.Resources$NotFoundException: Resource ID #0xffffffec

You'll notice on the last navigation; I told it to navigate to home/contact-tab/contact-tab-page
HOWEVER, somehow it failed that if test which triggered the path of code in _ProcessNextNavigationEntry where it makes the currentEntry null.

Event though I asked for contact-tab-page the page it is now attempting to navigate to is:
""home/about-tab/about-tab-page", (???? Where the hell did this value come from, the last time I navigated to it was navigation 7, we are now on Navigation 9 ????)
Because currentEntry is null (because of ProcessNextNavigationEntry makes it null) it uses the Default animation; which triggers the !!! fragment.transitions setCustomAnimations code that if you disable that single line of code it won't crash. However, eventually after a really large number of tries; I did manage to get the same error as Shiva got in his second example...


Update more logging:

Frame Navigate:  home/about-tab/about-tab-page
_ProcessNextNavigationEntry _currentEntry=null fragment3[0] home/contact-tab/contact-tab-page
+ NavCore {
  "moduleName": "home/contact-tab/contact-tab-page",
} Old: NULL -1 4
+ _setAndroidFragmentTransitions
Name after default
!!! fragment.transitions setCustomAnimations default Diff: false

Ok, this log appears to show the source of the issue. I've added the info for what page it is nulling out and each of the crashes appears to be because of this...

In this case I ask for home/about-tab/about-tab-page however, it somewhere (??? WHY ???) decided to navigate to home/contact-tab/contact-tab-page however the currententry that it just nulled out is the entry for home/contact-tab/contact-tab-page. So basically it is trying to navigate to the same page it is displaying; and I think the animation just goes wacky. I honestly don't understand how what I asked for changed to the existing page, I'm going to see if I can track that down...

All 8 comments

@shiv19 That's because it uses routing in the tab component. See this issue for more details.

@vahidvdn
I'm not using a TabView here, this is a different issue :)

HI @shiv19,
Thank you for the attached sample projects.
I was able to recreate the issue on my side and will mark this as a bug.
Regarding your case, I would suggest using the TabView provided by tns-core-modules instead of creating a custom one.

@tsonevn
The main goal of this custom implementation
Was to make that animation of the "tab highlight"

When you jump from tab 1 to say tab 4,
You can see the "tab highlight" travel across tabs 2 and 3 and stop at tab 4.

I've been experiencing this issue randomly for a number of months on Firebase/Crashlytics (partial data for the last 3 weeks):

File|Method|Users|Events
-|-|-|-
Resources.java โ€“ line 1233 | android.content.res.Resources.getValue | 1 | 1
Resources.java โ€“ line 1266 | android.content.res.Resources.getValue | 4 | 2
Resources.java โ€“ line 1269 | android.content.res.Resources.getValue | 1 | 1
Resources.java โ€“ line 1278 | android.content.res.Resources.getValue | 1 | 1
Resources.java โ€“ line 1281 | android.content.res.Resources.getValue | 1 | 1
Resources.java โ€“ line 1316 | android.content.res.Resources.getValue | 4 | 1
Resources.java โ€“ line 1359 | android.content.res.Resources.getValue | 1 | 1
Resources.java โ€“ line 1384 | android.content.res.Resources.getValue | 2 | 1
Resources.java โ€“ line 1397 | android.content.res.Resources.getValue | 1 | 1
Resources.java โ€“ line 1416 | android.content.res.Resources.getValue | 2 | 1
Resources.java โ€“ line 1457 | android.content.res.Resources.getValue | 3 | 2
Resources.java โ€“ line 1499 | android.content.res.Resources.getValue | 5 | 1
Resources.java โ€“ line 1524 | android.content.res.Resources.getValue | 1 | 1
Resources.java โ€“ line 1542 | android.content.res.Resources.getValue | 1 | 1
Resources.java โ€“ line 1544 | android.content.res.Resources.getValue | 10 | 9
Resources.java โ€“ line 1551 | android.content.res.Resources.getValue | 1 | 1
Resources.java โ€“ line 1577 | android.content.res.Resources.getValue | 1 | 1
Resources.java โ€“ line 2345 | android.content.res.Resources.getValue | 3 | 3
Resources.java โ€“ line 2495 | android.content.res.Resources.getValue | 3 | 3
Resources.java โ€“ line 2558 | android.content.res.Resources.getValue | 2 | 2
ResourcesImpl.java โ€“ line 190 | android.content.res.ResourcesImpl.getValue | 21 | 17
ResourcesImpl.java โ€“ line 198 | android.content.res.ResourcesImpl.getValue | 3 | 3
ResourcesImpl.java โ€“ line 201 | android.content.res.ResourcesImpl.getValue | 2 | 2
ResourcesImpl.java โ€“ line 202 | android.content.res.ResourcesImpl.getValue | 47 | 40
ResourcesImpl.java โ€“ line 204 | android.content.res.ResourcesImpl.getValue | 1 | 1
ResourcesImpl.java โ€“ line 207 | android.content.res.ResourcesImpl.getValue | 1 | 1
ResourcesImpl.java โ€“ line 208 | android.content.res.ResourcesImpl.getValue | 1 | 1
ResourcesImpl.java โ€“ line 210 | android.content.res.ResourcesImpl.getValue | 1 | 1
ResourcesImpl.java โ€“ line 216 | android.content.res.ResourcesImpl.getValue | 6 | 5
ResourcesImpl.java โ€“ line 255 | android.content.res.ResourcesImpl.getValue | 4 | 4
ResourcesImpl.java โ€“ line 279 | android.content.res.ResourcesImpl.getValue | 2 | 2

Fatal Exception: android.content.res.Resources$NotFoundException
Resource ID #0xffffffec
android.content.res.Resources.getValue (Resources.java:1544)
android.content.res.Resources.loadXmlResourceParser (Resources.java:3012)
android.content.res.Resources.getAnimation (Resources.java:1352)
android.animation.AnimatorInflater.loadAnimator (AnimatorInflater.java:122)
android.animation.AnimatorInflater.loadAnimator (AnimatorInflater.java:103)
android.animation.AnimatorInflater.loadAnimator (AnimatorInflater.java:88)
android.app.FragmentManagerImpl.loadAnimator (FragmentManager.java:831)
android.app.FragmentManagerImpl.moveToState (FragmentManager.java:1047)
android.app.FragmentManagerImpl.removeFragment (FragmentManager.java:1258)
android.app.BackStackRecord.run (BackStackRecord.java:751)
android.app.FragmentManagerImpl.execPendingActions (FragmentManager.java:1562)
android.app.FragmentManagerImpl$1.run (FragmentManager.java:487)
android.os.Handler.handleCallback (Handler.java:815)
android.os.Handler.dispatchMessage (Handler.java:104)
android.os.Looper.loop (Looper.java:207)
android.app.ActivityThread.main (ActivityThread.java:5728)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:789)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:679)

The line number and Resources/ResourcesImpl probably comes down to exactly which version of Android is being run, but the commonality is that it is always that it's an animation on a FragmentManager and the Resource ID #0xffffffec.

With some help from @NathanaelA , we realized that this number is -20 and after searching the code base I found this:
https://github.com/NativeScript/NativeScript/blob/master/tns-core-modules/ui/frame/fragment.transitions.d.ts#L13

It appears there is a possible chance of a race condition on the animations resulting in the fake resource being used.

Searching for Nativescript #0xffffffec I find these related tickets:
https://github.com/NativeScript/NativeScript/issues/1569 (2016)
https://github.com/NativeScript/NativeScript/issues/5549 -> https://github.com/NativeScript/android-runtime/issues/974 -> https://github.com/NativeScript/NativeScript/issues/5657

@tsonevn - The first case is actually a fairly critical bug that has been plaguing NS for a long time.
It is related to #5657, https://github.com/NativeScript/android-runtime/issues/974 and the later posted callstacks in #1569

@DickSmith and I was looking into the call stack earlier because he sees this in the PNP app logs frequently and we were trying to understand the android.content.res.Resources$NotFoundException: Resource ID #0xffffffec and specifically why 0xffffffec -- Well, we finally figured it out.

It occurred to me that that looked like a negative wrapping on a unsigned integer. So I went into a calculator and figured out that adding -20 to a unsigned int of 0 would = 0xffffffec. In addition

Specifically this line:
https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/content/res/ResourcesImpl.java#234

The Integer.toHexString(id)); guess what happens when you pass in -20. It outputs 0xffffffec. So now that we had the value being passed in -- I started the long process of walking back that stack trace to try and figure out where -20 gets assigned.

Richard, on the other hand was way smarter. :grinning: He started in the NS code and went forward. ;-) Guess what he found:
https://github.com/NativeScript/NativeScript/blob/master/tns-core-modules/ui/frame/fragment.transitions.d.ts#L13

That explains why Resource error of 0xffffffec is only associated with NativeScript apps. It is one of the 4 magic constants the NS team decided to use for transition animations.

Based on all the bug reports and looking at the call stacks; I believe what is happening is this:

This is basically a race condition; Two transitions racing, and one setting a valid transition id which is then replaced by -20 from the other one ending. I'm not 100% sure if the id is being set during the creation of the second transition starting or the second one ending. But somehow the one transition which is expecting a valid id; is getting the id for the other one ending with a -20...

After spending several more hours playing with the first demo; I can tell you this line of code causes the issue:
https://github.com/NativeScript/NativeScript/blob/master/tns-core-modules/ui/frame/fragment.transitions.android.ts#L153

If I comment out the issue; the crash is gone. Now the reason it runs this line is a bit weird. It seems the state gets messed up somehow.

Here is the log:

*********************************************************************
*** Notes:

    Frame Navigate is the call from the App; to switch the navigation; it output what is supposed to be navigated too next.
    +NavCore = Frame.prototype._navigateCore (frame.android it outputs the newEntry.entry and then currentEntry.entry)

    Name after: (xxxx) - this is the name of the animation choosen in the _setAndroidFragmentTransitions.    It is always "default" when it crashes because the currentEntry is null.

    !!! Fragment.transitions setCustomAnimations (Next to the crashing line, so I know if we hit this path)
     _ProcessNextNavigationEntry - this is the path where it sets _currentEntry to Null

     Fragment onFragmentCreateAnimator ( one of the locations that uses the newAnim value passed in, last one before a crash)
*********************************************************************


+ NavCore {
  "moduleName": "home/home-page"
} Old: NULL -1 -1
+ _setAndroidFragmentTransitions
Name after default
!!! fragment.transitions setCustomAnimations default Diff: false
+ Fragment onFragmentCreateAnimator: enter -10


+ NavCore {
  "moduleName": "home/home-tab/home-tab-page"
} Old: NULL 0 0
+ _setAndroidFragmentTransitions
Name after default
!!! fragment.transitions setCustomAnimations default Diff: false
+ Fragment onFragmentCreateAnimator: enter -10



Frame Navigate:  home/about-tab/about-tab-page slide
+ NavCore {
  "moduleName": "home/about-tab/about-tab-page",
} Old: {
  "moduleName": "home/home-tab/home-tab-page"
} 1 1
+ _setAndroidFragmentTransitions slide
Name after slide
+ Fragment onFragmentCreateAnimator: enter 0
+ Fragment onFragmentCreateAnimator: enter 0



Frame Navigate:  home/contact-tab/contact-tab-page slide
+ NavCore {
  "moduleName": "home/contact-tab/contact-tab-page",
} Old: {
  "moduleName": "home/about-tab/about-tab-page",
} 2 2
+ _setAndroidFragmentTransitions slide
Name after slide
- _setAndroidFragmentTransitions
+ Fragment onFragmentCreateAnimator: enter 0
+ Fragment onFragmentCreateAnimator: enter 0



Frame Navigate:  home/profile-tab/profile-tab-page slide
+ NavCore {
  "moduleName": "home/profile-tab/profile-tab-page",
} Old: {
  "moduleName": "home/contact-tab/contact-tab-page",
} 3 3
+ _setAndroidFragmentTransitions slide
Name after slide
+ Fragment onFragmentCreateAnimator: enter 0
+ Fragment onFragmentCreateAnimator: enter 0



...  (Even more entries deleted between id's 4 to 7 that succeeded) ...



Frame Navigate:  home/about-tab/about-tab-page slideRight
+ NavCore {
  "moduleName": "home/about-tab/about-tab-page",
} Old: {
  "moduleName": "home/contact-tab/contact-tab-page",
} 7 7
+ _setAndroidFragmentTransitions slideRight
Name after slideright
+ Fragment onFragmentCreateAnimator: enter 0
+ Fragment onFragmentCreateAnimator: enter 0


Frame Navigate:  home/home-tab/home-tab-page slideRight
+ NavCore {
  "moduleName": "home/home-tab/home-tab-page",
} Old: {
  "moduleName": "home/about-tab/about-tab-page",
} 8 8
+ _setAndroidFragmentTransitions slideRight
Name after slideright
+ Fragment onFragmentCreateAnimator: enter 0
+ Fragment onFragmentCreateAnimator: enter 0


******************************************************************************
** Here is where the log changes drastically and goes into the crash state...
******************************************************************************

Frame Navigate:  home/contact-tab/contact-tab-page slide
_ProcessNextNavigationEntry _currentEntry=null fragment8[8]
+ NavCore {
  "moduleName": "home/about-tab/about-tab-page",
} Old: NULL 9 9
+ _setAndroidFragmentTransitions
Name after default
!!! fragment.transitions setCustomAnimations default Diff: false
- _setAndroidFragmentTransitions
+ Fragment onFragmentCreateAnimator: enter -20

System.err: android.content.res.Resources$NotFoundException: Resource ID #0xffffffec

You'll notice on the last navigation; I told it to navigate to home/contact-tab/contact-tab-page
HOWEVER, somehow it failed that if test which triggered the path of code in _ProcessNextNavigationEntry where it makes the currentEntry null.

Event though I asked for contact-tab-page the page it is now attempting to navigate to is:
""home/about-tab/about-tab-page", (???? Where the hell did this value come from, the last time I navigated to it was navigation 7, we are now on Navigation 9 ????)
Because currentEntry is null (because of ProcessNextNavigationEntry makes it null) it uses the Default animation; which triggers the !!! fragment.transitions setCustomAnimations code that if you disable that single line of code it won't crash. However, eventually after a really large number of tries; I did manage to get the same error as Shiva got in his second example...


Update more logging:

Frame Navigate:  home/about-tab/about-tab-page
_ProcessNextNavigationEntry _currentEntry=null fragment3[0] home/contact-tab/contact-tab-page
+ NavCore {
  "moduleName": "home/contact-tab/contact-tab-page",
} Old: NULL -1 4
+ _setAndroidFragmentTransitions
Name after default
!!! fragment.transitions setCustomAnimations default Diff: false

Ok, this log appears to show the source of the issue. I've added the info for what page it is nulling out and each of the crashes appears to be because of this...

In this case I ask for home/about-tab/about-tab-page however, it somewhere (??? WHY ???) decided to navigate to home/contact-tab/contact-tab-page however the currententry that it just nulled out is the entry for home/contact-tab/contact-tab-page. So basically it is trying to navigate to the same page it is displaying; and I think the animation just goes wacky. I honestly don't understand how what I asked for changed to the existing page, I'm going to see if I can track that down...

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rLoka picture rLoka  ยท  3Comments

Pourya8366 picture Pourya8366  ยท  3Comments

NickIliev picture NickIliev  ยท  3Comments

dxshindeo picture dxshindeo  ยท  3Comments

OscarLopezArnaiz picture OscarLopezArnaiz  ยท  3Comments