Skip to content

Commit 402f0b1

Browse files
committed
Initial commit for better handling of background crashes
1 parent 70748fa commit 402f0b1

4 files changed

Lines changed: 44 additions & 1 deletion

File tree

app/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ dependencies {
227227
implementation 'androidx.fragment:fragment-ktx:1.6.2'
228228
implementation "androidx.lifecycle:lifecycle-livedata-ktx:${androidxLifecycleVersion}"
229229
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:${androidxLifecycleVersion}"
230+
implementation "androidx.lifecycle:lifecycle-process:${androidxLifecycleVersion}"
230231
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0'
231232
implementation 'androidx.media:media:1.7.0'
232233
implementation 'androidx.preference:preference:1.2.1'
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package org.schabi.newpipe.error
2+
3+
import android.util.Log
4+
import androidx.lifecycle.DefaultLifecycleObserver
5+
import androidx.lifecycle.LifecycleOwner
6+
import java.util.concurrent.atomic.AtomicLong
7+
8+
object AppLifecycleObserver : DefaultLifecycleObserver {
9+
private var isInBackground = false
10+
private val lastBackgroundTimestamp = AtomicLong(0)
11+
private var TAG = javaClass.simpleName
12+
13+
override fun onStart(owner: LifecycleOwner) {
14+
isInBackground = false
15+
Log.d(TAG, "App moved to foreground")
16+
}
17+
18+
override fun onStop(owner: LifecycleOwner) {
19+
isInBackground = true
20+
lastBackgroundTimestamp.set(System.currentTimeMillis())
21+
Log.d(TAG, "App moved to background")
22+
}
23+
24+
fun isAppInBackground(): Boolean = isInBackground
25+
26+
/**
27+
* @return the elapsed time since the app moved to the background or 0 if it is in foreground
28+
*/
29+
fun getTimeSinceLastBackground(): Long {
30+
return if (isInBackground) System.currentTimeMillis() - lastBackgroundTimestamp.get() else 0
31+
}
32+
}

app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,19 @@ class ErrorUtil {
3535
* activity (since the workflow would be interrupted anyway in that case). So never use this
3636
* for background services.
3737
*
38+
* If this method is called while the app has been in the background for more than
39+
* 10 seconds it will not start an error activity and instead create a notification
40+
*
3841
* @param context the context to use to start the new activity
3942
* @param errorInfo the error info to be reported
4043
*/
4144
@JvmStatic
4245
fun openActivity(context: Context, errorInfo: ErrorInfo) {
43-
context.startActivity(getErrorActivityIntent(context, errorInfo))
46+
if (AppLifecycleObserver.getTimeSinceLastBackground() > 10000) {
47+
createNotification(context, errorInfo)
48+
} else {
49+
context.startActivity(getErrorActivityIntent(context, errorInfo))
50+
}
4451
}
4552

4653
/**

app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import androidx.fragment.app.Fragment;
2929
import androidx.fragment.app.FragmentManager;
3030
import androidx.fragment.app.FragmentStatePagerAdapterMenuWorkaround;
31+
import androidx.lifecycle.ProcessLifecycleOwner;
3132
import androidx.preference.PreferenceManager;
3233
import androidx.viewpager.widget.ViewPager;
3334

@@ -36,6 +37,7 @@
3637
import org.schabi.newpipe.BaseFragment;
3738
import org.schabi.newpipe.R;
3839
import org.schabi.newpipe.databinding.FragmentMainBinding;
40+
import org.schabi.newpipe.error.AppLifecycleObserver;
3941
import org.schabi.newpipe.error.ErrorUtil;
4042
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
4143
import org.schabi.newpipe.local.playlist.LocalPlaylistFragment;
@@ -71,6 +73,7 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
7173
@Override
7274
public void onCreate(final Bundle savedInstanceState) {
7375
super.onCreate(savedInstanceState);
76+
ProcessLifecycleOwner.get().getLifecycle().addObserver(AppLifecycleObserver.INSTANCE);
7477
setHasOptionsMenu(true);
7578
tabsManager = TabsManager.getManager(activity);
7679
tabsManager.setSavedTabsListener(() -> {

0 commit comments

Comments
 (0)