简体   繁体   English

Android - 执行停止未恢复的活动

[英]Android - Performing stop of activity that is not resumed

When I push my app to background, and do some other stuff like whatsapp or sms, onResume it works great. 当我将我的应用程序推送到后台,并做一些其他的东西,如whatsapp或短信,onResume它很好。
But I recently discovered that when I open/launch facebook app while my app is on background, I don't know what happens... 但我最近发现,当我的应用程序在后台打开/启动Facebook应用程序时,我不知道会发生什么...
But onResume, the app misbehaves... 但是onResume,应用程序行为不端......
Don't do what it is required to do, but when I go back to homepage and come back it works fine Please help me out.. how to fix it ??? 不要做它需要做的事情,但当我回到主页并回来它工作正常请帮助我..如何解决它?

Logcat with all messages (without filter) 包含所有消息的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

And this is onResume() 这是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();
        }

    };

EDIT: HOW I FIXED THE ISSUE 编辑:我如何修复问题

I wrote this code in onResume() method 我在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();
}

One Line : It seems some of your activity variables were freed from memory as Android OS needed memory for the Facebook application. 一行 :由于Android操作系统需要Facebook应用程序的内存,因此您的某些活动变量似乎已从内存中释放出来。

Explanation : When an application in foreground needs more memory than that is available, Android frees some memory from the apps that are running in background. 说明 :当前台应用程序需要的内存多于可用内存时,Android会从后台运行的应用程序中释放一些内存。 Foreground tasks always have higher priority than background applications. 前台任务的优先级始终高于后台应用程序。

So, what might have happened to your application while it was in background is that some of its variables have lost their values which you are using in your onResume(). 因此,在应用程序处于后台时可能发生的情况是,它的某些变量已丢失了您在onResume()中使用的值。 Because of this they are holding wrong values or default values (you can check by using Sysout) as they are re-created when you again bring your app to foreground and due to which some of your code is not working right. 因此,当您再次将应用程序带到前台并且由于某些代码无法正常工作时,它们会重新创建,因此它们会保留错误的值或默认值(您可以使用Sysout进行检查)。

Just giving my 50 cents on the issue. 只是给我50美分的问题。 Catching the exception is indeed one possibility, but the correct way to deal with the issue of an activity being killed by the system for its resources in background is a common problem in android and according to Google the solution for this is: 捕获异常确实是一种可能性,但处理活动被系统杀死的活动问题的正确方法是在android中的常见问题,根据谷歌的解决方案是:

onPause() is where you deal with the user leaving your activity. onPause()是您处理离开活动的用户的地方。 Most importantly, any changes made by the user should at this point be committed (usually to the ContentProvider holding the data). 最重要的是, 此时应该提交用户所做的任何更改 (通常是提交数据的ContentProvider)。

Emphasis is mine. 重点是我的。 But what this means is that the Android lifecycles are designed so that under normal conditions onPause should be called as an Activity or Fragment is sent to the background. 但这意味着Android生命周期的设计是为了在正常条件下onPause应该被调用为ActivityFragment被发送到后台。 They hint at this in several of the android documentation pages : 他们在几个android文档页面中暗示了这一点:

As your activity enters the paused state, the system calls the onPause() method on your Activity, which allows you to stop ongoing actions that should not continue while paused (such as a video) or persist any information that should be permanently saved in case the user continues to leave your app. 当您的活动进入暂停状态时,系统会调用您的活动上的onPause()方法,该方法允许您停止暂停时不应继续的持续操作(例如视频)或保留应永久保存的任何信息以防万一用户继续离开您的应用。 If the user returns to your activity from the paused state, the system resumes it and calls the onResume() method. 如果用户从暂停状态返回到您的活动,系统将恢复它并调用onResume()方法。

Note: When your activity receives a call to onPause(), it may be an indication that the activity will be paused for a moment and the user may return focus to your activity. 注意:当您的活动收到对onPause()的调用时,可能表示活动暂停一段时间,用户可能会将焦点重新调整到您的活动。 However, it's usually the first indication that the user is leaving your activity. 但是,这通常是用户离开您的活动的第一个迹象。

But the resource that could most likely help you are these two: 但是最有可能帮助你的资源是这两个:

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

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

What's probably happening with your lost resources is this: 您丢失的资源可能发生的事情是这样的:

When your activity receives a call to the onStop() method, it's no longer visible and should release almost all resources that aren't needed while the user is not using it. 当您的活动收到对onStop()方法的调用时,它将不再可见,并且应该释放用户未使用时几乎所有不需要的资源。 Once your activity is stopped, the system might destroy the instance if it needs to recover system memory. 一旦您的活动停止,系统可能会在需要恢复系统内存时销毁该实例。 ... By default, the system uses the Bundle instance state to save information about each View object in your activity layout (such as the text value entered into an EditText object). ...默认情况下,系统使用Bundle实例状态来保存活动布局中每个View对象的信息(例如输入EditText对象的文本值)。 So, if your activity instance is destroyed and recreated, the state of the layout is restored to its previous state with no code required by you. 因此,如果您的活动实例被销毁并重新创建,则布局的状态将恢复到之前的状态,而您无需代码。 However, your activity might have more state information that you'd like to restore, such as member variables that track the user's progress in the activity. 但是,您的活动可能包含您要恢复的更多状态信息,例如跟踪用户在活动中的进度的成员变量。

Note: In order for the Android system to restore the state of the views in your activity, each view must have a unique ID, supplied by the android:id attribute. 注意:为了让Android系统恢复活动中视图的状态,每个视图必须具有唯一的ID,由android:id属性提供。

To save additional data about the activity state, you must override the onSaveInstanceState() callback method. 要保存有关活动状态的其他数据,必须覆盖onSaveInstanceState()回调方法。 The system calls this method when the user is leaving your activity and passes it the Bundle object that will be saved in the event that your activity is destroyed unexpectedly. 系统在用户离开您的活动时调用此方法,并将其传递给Bundle对象,该对象将在您的活动意外销毁时保存。 If the system must recreate the activity instance later, it passes the same Bundle object to both the onRestoreInstanceState() and onCreate() methods. 如果系统必须稍后重新创建活动实例,它会将相同的Bundle对象传递给onRestoreInstanceState()和onCreate()方法。

The correct solution for this is to override and implement the lifecycle methods of the Activity / Fragment as needed. 对此的正确解决方案是根据需要覆盖和实现Activity / Fragment的生命周期方法。

Two examples given by Google : 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.

And the reverse restore operation: 并且反向恢复操作:

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);
}

Hopefully you've addressed the issue already, but there is an error in your code, perhaps related: 希望你已经解决了这个问题,但你的代码中有一个错误,可能是相关的:

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

you are assigning instead of comparing in the "if" statement. 您要分配而不是在“if”语句中进行比较。 Should be: 应该:

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

or 要么

if (backgroundThreadRunning) {
    backgroundThreadRunning = false;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM