From 402f0b15aacc7a3d795bd4d4b33a8e3a082b31a0 Mon Sep 17 00:00:00 2001 From: Thompson3142 Date: Tue, 3 Dec 2024 00:51:15 +0100 Subject: [PATCH] Initial commit for better handling of background crashes --- app/build.gradle | 1 + .../newpipe/error/AppLifecycleObserver.kt | 32 +++++++++++++++++++ .../org/schabi/newpipe/error/ErrorUtil.kt | 9 +++++- .../newpipe/fragments/MainFragment.java | 3 ++ 4 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/org/schabi/newpipe/error/AppLifecycleObserver.kt diff --git a/app/build.gradle b/app/build.gradle index 662437f64..c082ef06e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -227,6 +227,7 @@ dependencies { implementation 'androidx.fragment:fragment-ktx:1.6.2' implementation "androidx.lifecycle:lifecycle-livedata-ktx:${androidxLifecycleVersion}" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:${androidxLifecycleVersion}" + implementation "androidx.lifecycle:lifecycle-process:${androidxLifecycleVersion}" implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0' implementation 'androidx.media:media:1.7.0' implementation 'androidx.preference:preference:1.2.1' diff --git a/app/src/main/java/org/schabi/newpipe/error/AppLifecycleObserver.kt b/app/src/main/java/org/schabi/newpipe/error/AppLifecycleObserver.kt new file mode 100644 index 000000000..5dfc62c63 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/error/AppLifecycleObserver.kt @@ -0,0 +1,32 @@ +package org.schabi.newpipe.error + +import android.util.Log +import androidx.lifecycle.DefaultLifecycleObserver +import androidx.lifecycle.LifecycleOwner +import java.util.concurrent.atomic.AtomicLong + +object AppLifecycleObserver : DefaultLifecycleObserver { + private var isInBackground = false + private val lastBackgroundTimestamp = AtomicLong(0) + private var TAG = javaClass.simpleName + + override fun onStart(owner: LifecycleOwner) { + isInBackground = false + Log.d(TAG, "App moved to foreground") + } + + override fun onStop(owner: LifecycleOwner) { + isInBackground = true + lastBackgroundTimestamp.set(System.currentTimeMillis()) + Log.d(TAG, "App moved to background") + } + + fun isAppInBackground(): Boolean = isInBackground + + /** + * @return the elapsed time since the app moved to the background or 0 if it is in foreground + */ + fun getTimeSinceLastBackground(): Long { + return if (isInBackground) System.currentTimeMillis() - lastBackgroundTimestamp.get() else 0 + } +} diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt index dcbc11413..3fa23aa8a 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt @@ -35,12 +35,19 @@ class ErrorUtil { * activity (since the workflow would be interrupted anyway in that case). So never use this * for background services. * + * If this method is called while the app has been in the background for more than + * 10 seconds it will not start an error activity and instead create a notification + * * @param context the context to use to start the new activity * @param errorInfo the error info to be reported */ @JvmStatic fun openActivity(context: Context, errorInfo: ErrorInfo) { - context.startActivity(getErrorActivityIntent(context, errorInfo)) + if (AppLifecycleObserver.getTimeSinceLastBackground() > 10000) { + createNotification(context, errorInfo) + } else { + context.startActivity(getErrorActivityIntent(context, errorInfo)) + } } /** diff --git a/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java index 381de5003..48087e911 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java @@ -28,6 +28,7 @@ import androidx.appcompat.app.ActionBar; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentStatePagerAdapterMenuWorkaround; +import androidx.lifecycle.ProcessLifecycleOwner; import androidx.preference.PreferenceManager; import androidx.viewpager.widget.ViewPager; @@ -36,6 +37,7 @@ import com.google.android.material.tabs.TabLayout; import org.schabi.newpipe.BaseFragment; import org.schabi.newpipe.R; import org.schabi.newpipe.databinding.FragmentMainBinding; +import org.schabi.newpipe.error.AppLifecycleObserver; import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.local.playlist.LocalPlaylistFragment; @@ -71,6 +73,7 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); + ProcessLifecycleOwner.get().getLifecycle().addObserver(AppLifecycleObserver.INSTANCE); setHasOptionsMenu(true); tabsManager = TabsManager.getManager(activity); tabsManager.setSavedTabsListener(() -> {