mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-20 19:18:37 +00:00
Fix ANR-like bug when resuming MainActivity.
This commit is contained in:
@@ -1,10 +1,10 @@
|
|||||||
package org.thoughtcrime.securesms;
|
package org.thoughtcrime.securesms;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewTreeObserver;
|
import android.view.ViewTreeObserver;
|
||||||
@@ -16,6 +16,7 @@ import androidx.lifecycle.ViewModelProvider;
|
|||||||
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||||
|
|
||||||
|
import org.signal.core.util.concurrent.LifecycleDisposable;
|
||||||
import org.thoughtcrime.securesms.components.DebugLogsPromptDialogFragment;
|
import org.thoughtcrime.securesms.components.DebugLogsPromptDialogFragment;
|
||||||
import org.thoughtcrime.securesms.components.PromptBatterySaverDialogFragment;
|
import org.thoughtcrime.securesms.components.PromptBatterySaverDialogFragment;
|
||||||
import org.thoughtcrime.securesms.components.voice.VoiceNoteMediaController;
|
import org.thoughtcrime.securesms.components.voice.VoiceNoteMediaController;
|
||||||
@@ -24,8 +25,7 @@ import org.thoughtcrime.securesms.conversationlist.RelinkDevicesReminderBottomSh
|
|||||||
import org.thoughtcrime.securesms.devicetransfer.olddevice.OldDeviceExitActivity;
|
import org.thoughtcrime.securesms.devicetransfer.olddevice.OldDeviceExitActivity;
|
||||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||||
import org.thoughtcrime.securesms.net.DeviceTransferBlockingInterceptor;
|
import org.thoughtcrime.securesms.net.DeviceTransferBlockingInterceptor;
|
||||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
import org.thoughtcrime.securesms.notifications.SlowNotificationsViewModel;
|
||||||
import org.thoughtcrime.securesms.notifications.SlowNotificationHeuristics;
|
|
||||||
import org.thoughtcrime.securesms.stories.tabs.ConversationListTabRepository;
|
import org.thoughtcrime.securesms.stories.tabs.ConversationListTabRepository;
|
||||||
import org.thoughtcrime.securesms.stories.tabs.ConversationListTabsViewModel;
|
import org.thoughtcrime.securesms.stories.tabs.ConversationListTabsViewModel;
|
||||||
import org.thoughtcrime.securesms.util.AppStartup;
|
import org.thoughtcrime.securesms.util.AppStartup;
|
||||||
@@ -33,7 +33,6 @@ import org.thoughtcrime.securesms.util.CachedInflater;
|
|||||||
import org.thoughtcrime.securesms.util.CommunicationActions;
|
import org.thoughtcrime.securesms.util.CommunicationActions;
|
||||||
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
|
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
|
||||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||||
import org.thoughtcrime.securesms.util.PowerManagerCompat;
|
|
||||||
import org.thoughtcrime.securesms.util.SplashScreenUtil;
|
import org.thoughtcrime.securesms.util.SplashScreenUtil;
|
||||||
import org.thoughtcrime.securesms.util.WindowUtil;
|
import org.thoughtcrime.securesms.util.WindowUtil;
|
||||||
|
|
||||||
@@ -46,6 +45,9 @@ public class MainActivity extends PassphraseRequiredActivity implements VoiceNot
|
|||||||
|
|
||||||
private VoiceNoteMediaController mediaController;
|
private VoiceNoteMediaController mediaController;
|
||||||
private ConversationListTabsViewModel conversationListTabsViewModel;
|
private ConversationListTabsViewModel conversationListTabsViewModel;
|
||||||
|
private SlowNotificationsViewModel slowNotificationsViewModel;
|
||||||
|
|
||||||
|
private final LifecycleDisposable lifecycleDisposable = new LifecycleDisposable();
|
||||||
|
|
||||||
private boolean onFirstRender = false;
|
private boolean onFirstRender = false;
|
||||||
|
|
||||||
@@ -80,6 +82,7 @@ public class MainActivity extends PassphraseRequiredActivity implements VoiceNot
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
lifecycleDisposable.bindTo(this);
|
||||||
|
|
||||||
mediaController = new VoiceNoteMediaController(this, true);
|
mediaController = new VoiceNoteMediaController(this, true);
|
||||||
|
|
||||||
@@ -95,6 +98,28 @@ public class MainActivity extends PassphraseRequiredActivity implements VoiceNot
|
|||||||
|
|
||||||
conversationListTabsViewModel = new ViewModelProvider(this, factory).get(ConversationListTabsViewModel.class);
|
conversationListTabsViewModel = new ViewModelProvider(this, factory).get(ConversationListTabsViewModel.class);
|
||||||
updateTabVisibility();
|
updateTabVisibility();
|
||||||
|
|
||||||
|
slowNotificationsViewModel = new ViewModelProvider(this).get(SlowNotificationsViewModel.class);
|
||||||
|
|
||||||
|
lifecycleDisposable.add(
|
||||||
|
slowNotificationsViewModel
|
||||||
|
.getSlowNotificationState()
|
||||||
|
.subscribe(this::presentSlowNotificationState)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NewApi")
|
||||||
|
private void presentSlowNotificationState(SlowNotificationsViewModel.State slowNotificationState) {
|
||||||
|
switch (slowNotificationState) {
|
||||||
|
case NONE:
|
||||||
|
break;
|
||||||
|
case PROMPT_BATTERY_SAVER_DIALOG:
|
||||||
|
PromptBatterySaverDialogFragment.show(getSupportFragmentManager());
|
||||||
|
break;
|
||||||
|
case PROMPT_DEBUGLOGS:
|
||||||
|
DebugLogsPromptDialogFragment.show(this, getSupportFragmentManager());
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -143,15 +168,7 @@ public class MainActivity extends PassphraseRequiredActivity implements VoiceNot
|
|||||||
|
|
||||||
updateTabVisibility();
|
updateTabVisibility();
|
||||||
|
|
||||||
if (SlowNotificationHeuristics.isHavingDelayedNotifications()) {
|
slowNotificationsViewModel.checkSlowNotificationHeuristics();
|
||||||
if (SlowNotificationHeuristics.isPotentiallyCausedByBatteryOptimizations() && Build.VERSION.SDK_INT >= 23) {
|
|
||||||
if (SlowNotificationHeuristics.shouldPromptBatterySaver()) {
|
|
||||||
PromptBatterySaverDialogFragment.show(this, getSupportFragmentManager());
|
|
||||||
}
|
|
||||||
} else if (SlowNotificationHeuristics.shouldPromptUserForLogs()) {
|
|
||||||
DebugLogsPromptDialogFragment.show(this, getSupportFragmentManager());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package org.thoughtcrime.securesms.components
|
package org.thoughtcrime.securesms.components
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@@ -27,7 +26,7 @@ class PromptBatterySaverDialogFragment : FixedRoundedCornerBottomSheetDialogFrag
|
|||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun show(context: Context, fragmentManager: FragmentManager) {
|
fun show(fragmentManager: FragmentManager) {
|
||||||
if (fragmentManager.findFragmentByTag(BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG) == null) {
|
if (fragmentManager.findFragmentByTag(BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG) == null) {
|
||||||
PromptBatterySaverDialogFragment().apply {
|
PromptBatterySaverDialogFragment().apply {
|
||||||
arguments = bundleOf()
|
arguments = bundleOf()
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ class NotificationsSettingsFragment : DSLSettingsFragment(R.string.preferences__
|
|||||||
title = DSLSettingsText.from(R.string.preferences_notifications__troubleshoot),
|
title = DSLSettingsText.from(R.string.preferences_notifications__troubleshoot),
|
||||||
isEnabled = true,
|
isEnabled = true,
|
||||||
onClick = {
|
onClick = {
|
||||||
PromptBatterySaverDialogFragment.show(requireContext(), childFragmentManager)
|
PromptBatterySaverDialogFragment.show(childFragmentManager)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 Signal Messenger, LLC
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.thoughtcrime.securesms.notifications
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
|
import io.reactivex.rxjava3.core.Observable
|
||||||
|
import io.reactivex.rxjava3.core.Single
|
||||||
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import io.reactivex.rxjava3.subjects.BehaviorSubject
|
||||||
|
import org.thoughtcrime.securesms.notifications.SlowNotificationHeuristics.isHavingDelayedNotifications
|
||||||
|
import org.thoughtcrime.securesms.notifications.SlowNotificationHeuristics.isPotentiallyCausedByBatteryOptimizations
|
||||||
|
import org.thoughtcrime.securesms.notifications.SlowNotificationHeuristics.shouldPromptBatterySaver
|
||||||
|
import org.thoughtcrime.securesms.notifications.SlowNotificationHeuristics.shouldPromptUserForLogs
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View model for checking for slow notifications and if we should prompt the user with help or for information.
|
||||||
|
*/
|
||||||
|
class SlowNotificationsViewModel : ViewModel() {
|
||||||
|
|
||||||
|
private val checkSubject = BehaviorSubject.create<Unit>()
|
||||||
|
|
||||||
|
val slowNotificationState: Observable<State>
|
||||||
|
|
||||||
|
init {
|
||||||
|
slowNotificationState = checkSubject
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(Schedulers.io())
|
||||||
|
.throttleFirst(1, TimeUnit.MINUTES)
|
||||||
|
.switchMapSingle {
|
||||||
|
checkHeuristics()
|
||||||
|
}
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkSlowNotificationHeuristics() {
|
||||||
|
checkSubject.onNext(Unit)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkHeuristics(): Single<State> {
|
||||||
|
return Single.fromCallable {
|
||||||
|
var state = State.NONE
|
||||||
|
if (isHavingDelayedNotifications()) {
|
||||||
|
if (isPotentiallyCausedByBatteryOptimizations() && Build.VERSION.SDK_INT >= 23) {
|
||||||
|
if (shouldPromptBatterySaver()) {
|
||||||
|
state = State.PROMPT_BATTERY_SAVER_DIALOG
|
||||||
|
}
|
||||||
|
} else if (shouldPromptUserForLogs()) {
|
||||||
|
state = State.PROMPT_DEBUGLOGS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return@fromCallable state
|
||||||
|
}.subscribeOn(Schedulers.io())
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class State {
|
||||||
|
NONE,
|
||||||
|
PROMPT_BATTERY_SAVER_DIALOG,
|
||||||
|
PROMPT_DEBUGLOGS
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
org.gradle.jvmargs=-Xmx4g -Xms256m -XX:MaxMetaspaceSize=1g
|
org.gradle.jvmargs=-Xmx6g -Xms256m -XX:MaxMetaspaceSize=1g
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
||||||
kapt.incremental.apt=false
|
kapt.incremental.apt=false
|
||||||
|
|||||||
Reference in New Issue
Block a user