我试图写一个应用程序,做一些具体的时候,它被带回前台后一段时间。是否有一种方法可以检测应用程序是被发送到后台还是被带到前台?
当前回答
我喜欢ProcessLifecycleOwner方法,但实际上可以跳过所有这些,因为在Activity的onCreate()方法中,可以很容易地确定它是第一次运行还是后续运行:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
/* savedInstanceState is always null on first run */
} else {
/* it's a subsequent run */
}
}
其他回答
考虑使用onUserLeaveHint。它只会在应用进入后台时被调用。onPause会有一些极端情况需要处理,因为它可以被用于其他原因;例如,如果用户在你的应用程序中打开另一个活动,比如你的设置页面,你的主活动的onPause方法将被调用,即使它们仍然在你的应用程序中;当你可以简单地使用onUserLeaveHint回调函数来做你所要求的事情时,跟踪正在进行的事情将导致错误。
当调用on UserLeaveHint时,你可以设置一个boolean inBackground标志为true。当onResume被调用时,如果inBackground标志被设置,只假设你回到前台。这是因为onResume也将被调用在你的主要活动,如果用户只是在你的设置菜单,从来没有离开应用程序。
Remember that if the user hits the home button while in your settings screen, onUserLeaveHint will be called in your settings activity, and when they return onResume will be called in your settings activity. If you only have this detection code in your main activity you will miss this use case. To have this code in all your activities without duplicating code, have an abstract activity class which extends Activity, and put your common code in it. Then each activity you have can extend this abstract activity.
例如:
public abstract AbstractActivity extends Activity {
private static boolean inBackground = false;
@Override
public void onResume() {
if (inBackground) {
// You just came from the background
inBackground = false;
}
else {
// You just returned from another activity within your own app
}
}
@Override
public void onUserLeaveHint() {
inBackground = true;
}
}
public abstract MainActivity extends AbstractActivity {
...
}
public abstract SettingsActivity extends AbstractActivity {
...
}
这里有一个解决方案,通过使用deboning逻辑,确保我们不会得到连续的背景/前景事件。所以,它总是反映一种稳定的背景/前景状态。
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import java.util.Timer
import java.util.TimerTask
/**
* An observer class to listen on the app's lifecycle.
*/
class AppLifecycleObserver(
private val onAppGoesToBackground: () -> Unit = {},
private val onAppEntersForeground: () -> Unit = {}
) : LifecycleEventObserver {
private val debounce = DebouncingTimer(timeout = 10)
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
debounce.refresh {
when (event.targetState) {
Lifecycle.State.CREATED -> onAppGoesToBackground()
Lifecycle.State.RESUMED -> onAppEntersForeground()
else -> Unit
}
}
}
fun attach() {
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
}
fun detach() {
ProcessLifecycleOwner.get().lifecycle.removeObserver(this)
}
private class DebouncingTimer(private val timeout: Long) {
private var timer: Timer? = null
fun refresh(job: () -> Unit) {
timer?.cancel()
timer = Timer()
timer?.schedule(object : TimerTask() {
override fun run() = job.invoke()
}, timeout)
}
}
}
只需要创建一个AppLifecycleObserver实例:
private val appLifecycleObserver = AppLifecycleObserver(
onAppGoesToBackground = { // do whatever... },
onAppEntersForeground = { // do whatever... }
)
// Attach the observer when it is needed:
appLifecycleObserver.attach()
// Remove when there is no need to it:
appLifecycleObserver.detach()
不要忘记添加一个合适的依赖版本:
implementation("androidx.lifecycle:lifecycle-process:$lifecycle_version")
在你的应用程序中添加回调并检查根活动,如下所示:
@Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
if (activity.isTaskRoot() && !(activity instanceof YourSplashScreenActivity)) {
Log.e(YourApp.TAG, "Reload defaults on restoring from background.");
loadDefaults();
}
}
});
}
My app needs to "reboot" after return from background - show a series of activities, according to client solicitations. After extensive search on how to manage the background/foreground transitions (treated very differently between iOS and Android), I crossed this question. Found very useful help here, specially from the most voted answer and the one flagged as correct. However, simply reinstantiate the root activity EVERY TIME the app enters foreground looked too annoying, when you think about UX. The solution that worked for me, and the one I think's most adequated - based on the Youtube and Twitter apps functionality - was to combine the answers from @GirishNair and @d60402: Calling the timer when the app's trimming memory, as follows:
@Override
public void onTrimMemory(int level) {
if (stateOfLifeCycle.equals("Stop")) {
startActivityTransitionTimer();
}
super.onTrimMemory(level);
}
我的定时器限制设置为30秒-我正在考虑增加一点。
private final long MAX_ACTIVITY_TRANSITION_TIME = 30000;
当app进入前台,重新启动,或者app被销毁时,调用方法取消定时器。
在应用程序扩展:
@Override
public void onActivityCreated(Activity activity, Bundle arg1) {
stopActivityTransitionTimer();
stateOfLifeCycle = "Create";
}
@Override
public void onActivityDestroyed(Activity activity) {
stopActivityTransitionTimer();
stateOfLifeCycle = "Destroy";
}
在活动上(最好是在一个基础活动上,由其他活动继承):
@Override
protected void onStart() {
super.onStart();
if (App.wasInBackground) {
stopActivityTransitionTimer();
}
}
在我的情况下,当应用程序在最大时间后进入前台时,会创建一个新任务,因此stopActivityTransitionTimer()在onActivityCreated()或onActivityDestroyed()上被调用,在应用程序扩展类中-转向不必要调用活动中的方法。 希望能有所帮助。
onPause()和onResume()方法在应用程序被带到后台并再次进入前台时被调用。但是,在应用程序第一次启动时和关闭之前也会调用它们。你可以在活动中阅读更多。
没有任何直接的方法来获得应用程序的状态,而在后台或前台,但即使我已经面临这个问题,并找到解决方案与onWindowFocusChanged和onStop。
更多细节请查看这里Android:解决方案检测当一个Android应用程序去后台,回到前台没有getRunningTasks或getRunningAppProcesses。
推荐文章
- 警告:API ' variable . getjavacompile()'已过时,已被' variable . getjavacompileprovider()'取代
- 安装APK时出现错误
- 碎片中的onCreateOptionsMenu
- TextView粗体通过XML文件?
- 如何使线性布局的孩子之间的空间?
- DSL元素android.dataBinding。enabled'已过时,已被'android.buildFeatures.dataBinding'取代
- ConstraintLayout:以编程方式更改约束
- PANIC: AVD系统路径损坏。检查ANDROID_SDK_ROOT值
- 如何生成字符串类型的buildConfigField
- Recyclerview不调用onCreateViewHolder
- Android API 21工具栏填充
- Android L中不支持操作栏导航模式
- 如何在TextView中添加一个子弹符号?
- PreferenceManager getDefaultSharedPreferences在Android Q中已弃用
- 在Android Studio中创建aar文件