Turns out that the crash I thought will not occur with #4153 did occur
again. 😒
But this time I managed to reproduce it (faking a slow network for that
one request only and then quickly switching activities to get it
destroyed) so I'm sure it is fixed, and I did a check for possible side
effects but it seems Glide is clever enough to cancel all requests by
itself.
<details>
<summary>stacktrace</summary>
```
Exception java.lang.IllegalArgumentException: You cannot start a load for a destroyed activity
at com.bumptech.glide.manager.RequestManagerRetriever.assertNotDestroyed (RequestManagerRetriever.java:236)
at com.bumptech.glide.manager.RequestManagerRetriever.get (RequestManagerRetriever.java:110)
at com.bumptech.glide.manager.RequestManagerRetriever.get (RequestManagerRetriever.java:176)
at com.bumptech.glide.Glide.with (Glide.java:634)
at com.keylesspalace.tusky.MainActivity$setupDrawer$2.cancel (MainActivity.kt:573)
at com.mikepenz.materialdrawer.util.DrawerImageLoader.cancelImage (DrawerImageLoader.java:56)
at com.mikepenz.materialdrawer.model.BaseDescribeableDrawerItem.unbindView (BaseDescribeableDrawerItem.kt:95)
at com.mikepenz.materialdrawer.model.BaseDescribeableDrawerItem.unbindView (BaseDescribeableDrawerItem.kt:20)
at com.mikepenz.fastadapter.listeners.OnBindViewHolderListenerImpl.unBindViewHolder (OnBindViewHolderListenerImpl.java:36)
at com.mikepenz.fastadapter.FastAdapter.onViewRecycled (FastAdapter.kt:410)
at androidx.recyclerview.widget.RecyclerView$Recycler.dispatchViewRecycled (RecyclerView.java:7346)
at androidx.recyclerview.widget.RecyclerView$Recycler.addViewHolderToRecycledViewPool (RecyclerView.java:7108)
at androidx.recyclerview.widget.RecyclerView$Recycler.recycleViewHolderInternal (RecyclerView.java:7059)
at androidx.recyclerview.widget.RecyclerView.removeAnimatingView (RecyclerView.java:1556)
at androidx.recyclerview.widget.RecyclerView$ItemAnimatorRestoreListener.onAnimationFinished (RecyclerView.java:13564)
at androidx.recyclerview.widget.RecyclerView$ItemAnimator.dispatchAnimationFinished (RecyclerView.java:14066)
at androidx.recyclerview.widget.SimpleItemAnimator.dispatchChangeFinished (SimpleItemAnimator.java:328)
at androidx.recyclerview.widget.DefaultItemAnimator.endChangeAnimationIfNecessary (DefaultItemAnimator.java:437)
at androidx.recyclerview.widget.DefaultItemAnimator.endChangeAnimationIfNecessary (DefaultItemAnimator.java:418)
at androidx.recyclerview.widget.DefaultItemAnimator.endAnimations (DefaultItemAnimator.java:588)
at androidx.recyclerview.widget.RecyclerView.onDetachedFromWindow (RecyclerView.java:3383)
at android.view.View.dispatchDetachedFromWindow (View.java:20898)
at android.view.ViewGroup.dispatchDetachedFromWindow (ViewGroup.java:3956)
at android.view.ViewGroup.dispatchDetachedFromWindow (ViewGroup.java:3948)
at android.view.ViewGroup.dispatchDetachedFromWindow (ViewGroup.java:3948)
at android.view.ViewGroup.dispatchDetachedFromWindow (ViewGroup.java:3948)
at android.view.ViewGroup.dispatchDetachedFromWindow (ViewGroup.java:3948)
at android.view.ViewGroup.dispatchDetachedFromWindow (ViewGroup.java:3948)
at android.view.ViewGroup.dispatchDetachedFromWindow (ViewGroup.java:3948)
at android.view.ViewGroup.dispatchDetachedFromWindow (ViewGroup.java:3948)
at android.view.ViewRootImpl.dispatchDetachedFromWindow (ViewRootImpl.java:5114)
at android.view.ViewRootImpl.doDie (ViewRootImpl.java:8309)
at android.view.ViewRootImpl.die (ViewRootImpl.java:8286)
at android.view.WindowManagerGlobal.removeViewLocked (WindowManagerGlobal.java:538)
at android.view.WindowManagerGlobal.removeView (WindowManagerGlobal.java:479)
at android.view.WindowManagerImpl.removeViewImmediate (WindowManagerImpl.java:162)
at android.app.ActivityThread.handleDestroyActivity (ActivityThread.java:5564)
at android.app.ActivityThread.handleRelaunchActivityInner (ActivityThread.java:5842)
at android.app.ActivityThread.handleRelaunchActivity (ActivityThread.java:5758)
at android.app.servertransaction.ActivityRelaunchItem.execute (ActivityRelaunchItem.java:71)
at android.app.servertransaction.ActivityTransactionItem.execute (ActivityTransactionItem.java:45)
at android.app.servertransaction.TransactionExecutor.executeCallbacks (TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2293)
at android.os.Handler.dispatchMessage (Handler.java:106)
at android.os.Looper.loopOnce (Looper.java:226)
at android.os.Looper.loop (Looper.java:329)
at android.app.ActivityThread.main (ActivityThread.java:8058)
at java.lang.reflect.Method.invoke
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1026)
```
</details>
<details>
<summary>Stacktrace</summary>
```
java.lang.ClassCastException: java.lang.String cannot be cast to
android.text.Spannable
at
com.keylesspalace.tusky.view.ClickableSpanTextView.dispatchTouchEvent(ClickableSpanTextView.kt:208)
at
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2968)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2600)
at
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2968)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2600)
at
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2968)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2600)
at
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2968)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2600)
at
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2968)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2600)
at
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2968)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2600)
at
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2968)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2600)
at
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2968)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2600)
at
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2968)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2600)
at
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2968)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2600)
at
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2968)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2600)
at
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2968)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2600)
at
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2968)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2600)
at
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2968)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2600)
at
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2968)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2600)
at
com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:448)
at
com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1829)
at android.app.Activity.dispatchTouchEvent(Activity.java:3307)
at
androidx.appcompat.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:70)
at
com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:410)
at android.view.View.dispatchPointerEvent(View.java:12015)
at
android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4795)
at
android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4609)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4147)
at
android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4200)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4166)
at
android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4293)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4174)
at
android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4350)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4147)
at
android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4200)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4166)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4174)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4147)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6661)
```
</details>
Could not reproduce with a regular build because I couldn't find the
place where we set a string into a ClickableSpanTextView, so I created
that scenario manually. It crashed instantly when trying to select text,
and with this fix it behaved as expected.
Saw an ANR (app not responding) error being reported in the Play console
and then found this. Sorry but `runBlocking` in production code is an
absolute no go.
```
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.keylesspalace.tusky.test/com.keylesspalace.tusky.ViewMediaActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2778)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: java.lang.NullPointerException
at com.keylesspalace.tusky.ViewMediaActivity.adjustScreenWakefulness(ViewMediaActivity.kt:351)
at com.keylesspalace.tusky.ViewMediaActivity.onCreate(ViewMediaActivity.kt:161)
at android.app.Activity.performCreate(Activity.java:7009)
at android.app.Activity.performCreate(Activity.java:7000)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2731)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
```
Currently translated at 100.0% (634 of 634 strings)
Translated using Weblate (Russian)
Currently translated at 100.0% (634 of 634 strings)
Co-authored-by: Vladyslav Stepanov <mittwerk@users.noreply.weblate.tusky.app>
Translate-URL: https://weblate.tusky.app/projects/tusky/tusky/ru/
Translation: Tusky/Tusky
For reasons not totally clear to me, Github marked #4160 as "merged" and
will not let me reopen it.
I believe this should be included for 24.1 because it fixes a 24.0
regression in the media player.
I have tested this newest commit in a number of ways, and in my testing
I find (1) when viewing an image, it sleeps after about a minute (2)
when viewing video, it stays awake indefinitely (3) this is true whether
the image/video was opened directly, or reached by swiping from another
attachment. I have not tested swiping to/from audio but I am confident
it will work the same.
I hate these workarounds for Android bugs, I'm always afraid the will
introduce other problems. I tested this on multiple Android versions, it
definitely fixes the problem and otherwise seems fine though.
closes#4164
Currently translated at 100.0% (634 of 634 strings)
Co-authored-by: fin-w <puf@users.noreply.weblate.tusky.app>
Translate-URL: https://weblate.tusky.app/projects/tusky/tusky/cy/
Translation: Tusky/Tusky
Another fix for a memory leak. This one is not as big as #4150, but
still worth fixing for memory constrained devices imo.
The `DrawerImageLoader` implementation (a global singleton) references a
member of the `MainActivity`, causing the whole activity to leak.
This weird construct was introduced in #1989 to fix a crash, but I think
since we migrated to coroutines it is no longer necessary because all
calls get correctly cancelled. I tried reproducing the crash but could
not, so I'm pretty sure it is fine. I would appreciate it if someone
else could try it as well though.
(The crash could be reproduced on slow internet, when
`onFetchUserInfoSuccess` was called while the activity was being
destroyed, causing Glide to crash the app because it can't use destroyed
activities. `onFetchUserInfoSuccess` is now no longer called in this
case because it is inside a `lifecycleScope.launch` block.)
Found with Leak canary: The transformation ends up in Glide's memory
cache and leaks whole Activities through the view -> context reference.
This fixes the problem by removing the background detection logic (so
the view reference is no longer needed) and setting the background
directly instead. Looks exactly as before.