Когда я переключаю свое приложение в фоновый режим и делаю что-то еще, например, WhatsApp или смс, onResume отлично работает.
Но недавно я обнаружил, что когда я открываю / запускаю приложение facebook в фоновом режиме, я не знаю, что происходит ...
Но onResume, приложение плохо себя ведет ...
Не делайте того, что от него требуется, но когда я возвращаюсь на главную страницу и возвращаюсь, все работает нормально. Помогите пожалуйста .. как исправить ???

Logcat со всеми сообщениями (без фильтра)

10-15 12:53:59.899: I/Adreno-EGL(32033): Remote Branch: quic/LNX.LA.3.5.1_RB1.1
10-15 12:53:59.899: I/Adreno-EGL(32033): Local Patches: NONE
10-15 12:53:59.899: I/Adreno-EGL(32033): Reconstruct Branch: AU_LINUX_ANDROID_LNX.LA.3.5.1_RB1.04.04.02.048.018 + f2fd134 +  NOTHING
10-15 12:53:59.924: D/OpenGLRenderer(32033): Enabling debug mode 0
10-15 12:54:00.000: V/AlarmManager(7677): sending alarm Alarm{42cfa490 type 3 android}
10-15 12:54:00.110: I/ActivityManager(7677): Displayed uk.org.humanfocus.hfi/.EvaluateTrainingActivity: +838ms
10-15 12:54:00.114: D/WifiStateMachine(7677): handleMessage: E msg.what=151572
10-15 12:54:00.114: D/WifiStateMachine(7677): processMsg: ConnectedState
10-15 12:54:00.114: D/WifiStateMachine(7677): processMsg: L2ConnectedState
10-15 12:54:02.258: V/AlarmManager(7677): sending alarm Alarm{42ebd600 type 1 com.facebook.katana}
10-15 12:54:02.274: V/AlarmManager(7677): sending alarm Alarm{42ec0ff0 type 1 com.android.chrome}
10-15 12:54:02.428: D/hardware_info(7386): hw_info_append_hw_type : device_name = speaker
10-15 12:54:03.011: W/BroadcastQueue(7677): Permission Denial: broadcasting Intent { act=android.net.conn.INET_CONDITION_ACTION flg=0x4000010 (has extras) } from null (pid=-1, uid=-1) requires com.facebook.permission.prod.FB_APP_COMMUNICATION due to registered receiver BroadcastFilter{41fdecd0 u0 ReceiverList{42b2f608 31941 com.facebook.katana/10103/u0 remote:429a17e8}}
10-15 12:54:03.011: W/BroadcastQueue(7677): Permission Denial: broadcasting Intent { act=android.net.conn.CONNECTIVITY_CHANGE flg=0x4000010 (has extras) } from null (pid=-1, uid=-1) requires com.facebook.permission.prod.FB_APP_COMMUNICATION due to registered receiver BroadcastFilter{41fdecd0 u0 ReceiverList{42b2f608 31941 com.facebook.katana/10103/u0 remote:429a17e8}}
10-15 12:54:03.118: D/WifiStateMachine(7677): handleMessage: E msg.what=151572
10-15 12:54:03.118: D/WifiStateMachine(7677): processMsg: ConnectedState
10-15 12:54:03.118: D/WifiStateMachine(7677): processMsg: L2ConnectedState
10-15 12:54:03.140: D/WifiStateMachine(7677): handleMessage: X
10-15 12:54:03.141: D/GCoreFlp(8174): Unknown pending intent to remove.
10-15 12:54:03.145: W/fb4a(:<default>):AbstractMqttPushService(31941): Attempt to start service that is already started
10-15 12:54:03.242: D/WifiStateMachine(7677): handleMessage: E msg.what=131155
10-15 12:54:03.242: D/WifiStateMachine(7677): processMsg: ConnectedState
10-15 12:54:03.243: D/WifiStateMachine(7677): processMsg: L2ConnectedState
10-15 12:54:03.245: D/WifiStateMachine(7677): handleMessage: X
10-15 12:54:03.319: D/dalvikvm(31941): GC_CONCURRENT freed 1833K, 9% free 20190K/22072K, paused 5ms+7ms, total 86ms
10-15 12:54:03.320: D/dalvikvm(31941): WAIT_FOR_CONCURRENT_GC blocked 68ms
10-15 12:54:03.323: W/MediaPlayer-JNI(31941): MediaPlayer finalized without being released
10-15 12:54:03.452: W/BroadcastQueue(7677): Permission Denial: broadcasting Intent { act=android.net.conn.CONNECTIVITY_CHANGE flg=0x4000010 (has extras) } from null (pid=-1, uid=-1) requires com.facebook.permission.prod.FB_APP_COMMUNICATION due to registered receiver BroadcastFilter{42b51d68 u0 ReceiverList{429feb50 31941 com.facebook.katana/10103/u0 remote:41fb8788}}
10-15 12:54:03.573: W/fb4a(:<default>):JACKSON_FALLBACK(31941): Using com.fasterxml.jackson.databind.deser.std.EnumDeserializer@42914bc8 to deserialize [simple type, class com.facebook.common.util.TriState]
10-15 12:54:03.587: W/fb4a(:<default>):JACKSON_FALLBACK(31941): Using com.fasterxml.jackson.databind.deser.std.EnumDeserializer@42bb3100 to deserialize [simple type, class com.facebook.contacts.graphql.contactprofiletype.ContactProfileType]
10-15 12:54:03.957: D/dalvikvm(31941): GC_CONCURRENT freed 3400K, 15% free 20455K/23952K, paused 4ms+7ms, total 88ms
10-15 12:54:03.957: D/dalvikvm(31941): WAIT_FOR_CONCURRENT_GC blocked 75ms
10-15 12:54:04.099: W/fb4a(:<default>):JACKSON_FALLBACK(31941): Using BeanSerializer for com.facebook.katana.newbookmark.qe.NewBookmarkConfig to serialize class com.facebook.katana.newbookmark.qe.NewBookmarkConfig
10-15 12:54:04.119: D/WifiStateMachine(7677): handleMessage: E msg.what=151572
10-15 12:54:04.120: D/WifiStateMachine(7677): processMsg: ConnectedState
10-15 12:54:04.120: D/WifiStateMachine(7677): processMsg: L2ConnectedState
10-15 12:54:04.124: D/WifiStateMachine(7677): handleMessage: X
10-15 12:54:04.177: W/fb4a(:<default>):JACKSON_FALLBACK(31941): Using com.fasterxml.jackson.databind.deser.std.EnumDeserializer@42a30980 to deserialize [simple type, class com.facebook.platform.webdialogs.PlatformWebViewActionManifest$FetchState]
10-15 12:54:04.197: I/dalvikvm(31941): Could not find method com.android.internal.widget.ILockSettings$Stub.a, referenced from method com.facebook.keyguardtype.LockSettingsServiceKeyguardTypeResolver.b
10-15 12:54:04.197: W/dalvikvm(31941): VFY: unable to resolve static method 5338: Lcom/android/internal/widget/ILockSettings$Stub;.a (Landroid/os/IBinder;)Lcom/android/internal/widget/ILockSettings;
10-15 12:54:04.197: D/dalvikvm(31941): VFY: replacing opcode 0x71 at 0x0023
10-15 12:54:04.440: I/SBar.NetworkController(7758): onSignalStrengthsChanged SignalStrength: 19 0 -120 -160 -120 -1 -1 99 2147483647 2147483647 2147483647 2147483647 2147483647 gsm|lte 0 -108 -1 false 5 5 0 0 0 99 99 99 5 level=5
10-15 12:54:04.814: V/WebViewChromiumFactoryProvider(31941): Binding Chromium to main looper Looper (main, tid 1) {41f8cbd0}
10-15 12:54:04.815: I/LibraryLoader(31941): Expected native library version number "",actual native library version number ""
10-15 12:54:04.816: I/chromium(31941): [INFO:library_loader_hooks.cc(116)] Chromium logging enabled: level = 0, default verbosity = 0
10-15 12:54:04.817: I/BrowserStartupController(31941): Initializing chromium process, renderers=0
10-15 12:54:04.822: E/AudioManagerAndroid(31941): BLUETOOTH permission is missing!
10-15 12:54:04.864: W/chromium(31941): [WARNING:proxy_service.cc(890)] PAC support disabled because there is no system implementation
10-15 12:54:05.121: D/WifiStateMachine(7677): handleMessage: E msg.what=151572
10-15 12:54:05.121: D/WifiStateMachine(7677): processMsg: ConnectedState
10-15 12:54:05.122: D/WifiStateMachine(7677): processMsg: L2ConnectedState

И это onResume ()

super.onResume();

        if (backgroundThreadRunning == true) {
            backgroundThreadRunning = false;
        }

        if (Constants.isVideoEditing)
            editingProgress.setVisibility(View.VISIBLE);
        else
            editingProgress.setVisibility(View.GONE);

        if (Constants.isAudioProcessing)
            addAudioProgress.setVisibility(View.VISIBLE);
        else
            addAudioProgress.setVisibility(View.GONE);

        if (isHomeKeyPressed() && !(isRecentActivity)) {
            isRecentActivity = false;
            homeKeyPressed(false);
            AlertDialog.Builder ab = new AlertDialog.Builder(
                    CreateTrainingActivity.this);
            ab.setMessage(
                    "Due to Other Application Launches, video process will be cancelled!\nAre you sure you want to cancel?")
                    .setPositiveButton("Yes", dialogClickListener)
                    .setNegativeButton("No", dialogClickListener).show();
        }

    };

РЕДАКТИРОВАТЬ: КАК Я УСТРАНИЛ ПРОБЛЕМУ

Я написал этот код в методе onResume()

try {
    // check if any view exists on current view
    style = ((Button) findViewById(R.id.xyz_button));   
} catch (Exception e) {
    // Button was not found
    // It means, your button doesn't exist on the "current" view
    // It was freed from the memory, therefore stop of activity was performed
    // In this case I restart my app
    Intent i = new Intent();
    i.setClass(getApplicationContext(), MainActivity.class);
    i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    startActivity(i);
    // Show toast to the user
    Toast.makeText(getApplicationContext(), "Data lost due to excess use of other apps", Toast.LENGTH_LONG).show();
}
40
Salmaan 15 Окт 2014 в 10:33

3 ответа

Лучший ответ

Просто отдаю свои 50 центов по этому вопросу. Выявление исключения - это действительно одна из возможностей, но правильный способ решения проблемы, связанной с отключением активности системой из-за ее ресурсов в фоновом режиме, является распространенной проблемой в Android, и, согласно Google, решение для этого:

onPause () - это то место, где вы имеете дело с пользователем, покидающим вашу деятельность. Самое главное, любые изменения, внесенные пользователем, на этом этапе должны быть зафиксированы (обычно в ContentProvider, хранящем данные).

Акцент мой. Но это означает, что жизненные циклы Android спроектированы таким образом, что при нормальных условиях onPause должен вызываться как Activity или Fragment отправляется в фоновый режим. Они намекают на это на нескольких страницах документации Android:

Когда ваше действие переходит в состояние паузы, система вызывает метод onPause () для вашего действия, который позволяет вам остановить текущие действия, которые не должны продолжаться во время паузы (например, видео), или сохранить любую информацию, которая должна быть сохранена навсегда в случае пользователь продолжает покидать ваше приложение. Если пользователь возвращается к вашей активности из приостановленного состояния, система возобновляет ее и вызывает метод onResume ().

Примечание. Когда ваше действие получает вызов onPause (), это может указывать на то, что действие будет приостановлено на мгновение, и пользователь может вернуть фокус вашему действию. Однако обычно это первое указание на то, что пользователь покидает вашу деятельность.

Но ресурсы, которые, скорее всего, могут вам помочь, это два:

http://developer.android.com/training/basics/activity-lifecycle/stopping.html

http://developer.android.com/training/basics/activity-lifecycle/recreating.html

Вероятно, с вашими потерянными ресурсами происходит следующее:

Когда ваша операция получает вызов метода onStop (), она больше не отображается и должна высвободить почти все ресурсы, которые не нужны, пока пользователь ее не использует. Как только ваша деятельность будет остановлена, система может уничтожить экземпляр, если ей потребуется восстановить системную память. ... По умолчанию система использует состояние экземпляра Bundle для сохранения информации о каждом объекте View в макете действия (например, текстовое значение, введенное в объект EditText). Итак, если ваш экземпляр действия уничтожен и воссоздан заново, состояние макета будет восстановлено до предыдущего состояния без кода, необходимого вам. Однако у вашей активности может быть больше информации о состоянии, которую вы хотели бы восстановить, например, переменные-члены, которые отслеживают прогресс пользователя в действии.

Примечание. Чтобы система Android могла восстановить состояние представлений в вашей деятельности, каждое представление должно иметь уникальный идентификатор, предоставляемый атрибутом android: id.

Чтобы сохранить дополнительные данные о состоянии активности, необходимо переопределить метод обратного вызова onSaveInstanceState (). Система вызывает этот метод, когда пользователь покидает ваше действие, и передает ему объект Bundle, который будет сохранен в случае неожиданного уничтожения вашего действия. Если позже системе необходимо воссоздать экземпляр действия, она передает один и тот же объект Bundle в методы onRestoreInstanceState () и onCreate ().

Правильным решением для этого является переопределение и реализация методов жизненного цикла Activity / Fragment по мере необходимости.

Два примера приведены Google:

    static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
...

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Save the user's current game state
    savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
    savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);

    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);
}
Caution: Always call the superclass implementation of onSaveInstanceState() so the default implementation can save the state of the view hierarchy.

И обратная операция восстановления:

public void onRestoreInstanceState(Bundle savedInstanceState) {
    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState);

    // Restore state members from saved instance
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
    mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}
15
HenriqueMS 13 Май 2016 в 18:29
1
Да, это то, что я понял после решения нескольких подобных проблем.
 – 
Salmaan
16 Май 2016 в 09:07
1
Спасибо за подробный ответ и прозвон по ключевым моментам, а также за пример кода. Это очень полезно.
 – 
John Ward
29 Янв 2017 в 02:14
Без проблем, рад помочь;)
 – 
HenriqueMS
29 Янв 2017 в 02:16

Одна строка . Похоже, что некоторые из переменных вашей активности были освобождены из памяти, поскольку ОС Android требовалась память для приложения Facebook.

Объяснение : когда приложению на переднем плане требуется больше памяти, чем доступно, Android освобождает часть памяти из приложений, работающих в фоновом режиме. Задачи переднего плана всегда имеют более высокий приоритет, чем фоновые приложения.

Итак, что могло случиться с вашим приложением в фоновом режиме, так это то, что некоторые из его переменных потеряли свои значения, которые вы используете в своем onResume (). Из-за этого они содержат неправильные значения или значения по умолчанию (вы можете проверить с помощью Sysout), поскольку они воссоздаются, когда вы снова переводите свое приложение на передний план, и из-за чего часть вашего кода работает неправильно.

28
brunobowden 25 Апр 2015 в 09:03
3
Так что мне делать, чтобы избежать этого?
 – 
Salmaan
15 Окт 2014 в 14:03
1
По сути, вам нужно проверить, какая из ваших переменных теряет данные. Затем вам нужно разработать логику в соответствии с вашим приложением, которое должно хранить значение, чтобы вы могли использовать его в своем onResume().
 – 
Whisky
15 Окт 2014 в 14:08
Можете ли вы поделиться фрагментом кода, как проверить с помощью sysout?
 – 
Ajay S
16 Ноя 2014 в 22:27
Проверьте с помощью sysout! считайте, что mVar - это переменная (скажем, String), и ее значение = "hello world" вы можете ввести: Log.d ("Tag", "Variable mVar value is: "+mVar +"!!!"); это напечатает: Значение переменной mVar: hello world!!!
 – 
Esmaeel Ibraheem
17 Фев 2015 в 11:38

Надеюсь, вы уже решили проблему, но в вашем коде есть ошибка, возможно, связанная с:

if (backgroundThreadRunning = true) {
    backgroundThreadRunning = false;
}

Вы назначаете вместо сравнения в операторе «if». Должно быть:

if (backgroundThreadRunning == true) {
    backgroundThreadRunning = false;
}

Или

if (backgroundThreadRunning) {
    backgroundThreadRunning = false;
}
7
noelicus 16 Янв 2017 в 19:55
6
Или backgroundThreadRunning = false; так как он все равно будет установлен в false.
 – 
kareblak
6 Янв 2015 в 17:46
1
Насколько я знаю, Android Studio (Lint) помечает это совпадение как ошибку. Невозможно написать: если (а = b)...
 – 
CoolMind
17 Янв 2016 в 18:49
1
Результатом выражения присваивания (a = b) является само a. Поскольку a в данном случае логическое значение, оно работает. Java понимает это как if (a itself after the assignment has been done).
 – 
Piovezan
28 Янв 2016 в 19:22
@Piovezan, да, ты прав, это верно для логических значений.
 – 
CoolMind
29 Янв 2016 в 12:36