我试图写一个应用程序,做一些具体的时候,它被带回前台后一段时间。是否有一种方法可以检测应用程序是被发送到后台还是被带到前台?
当前回答
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()上被调用,在应用程序扩展类中-转向不必要调用活动中的方法。 希望能有所帮助。
其他回答
正确答案
创建名为MyApp的类,如下所示:
public class MyApp implements Application.ActivityLifecycleCallbacks, ComponentCallbacks2 {
private Context context;
public void setContext(Context context)
{
this.context = context;
}
private boolean isInBackground = false;
@Override
public void onTrimMemory(final int level) {
if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
isInBackground = true;
Log.d("status = ","we are out");
}
}
@Override
public void onActivityCreated(Activity activity, Bundle bundle) {
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
if(isInBackground){
isInBackground = false;
Log.d("status = ","we are in");
}
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
@Override
public void onConfigurationChanged(Configuration configuration) {
}
@Override
public void onLowMemory() {
}
}
然后,在你想要的任何地方(最好是在应用程序中启动的第一个活动),添加下面的代码:
MyApp myApp = new MyApp();
registerComponentCallbacks(myApp);
getApplication().registerActivityLifecycleCallbacks(myApp);
完成了!现在当应用程序在后台时,我们得到日志状态:我们退出 当我们进入app,我们得到log status,我们是out
这似乎是Android中最复杂的问题之一,因为(在撰写本文时)Android没有iOS中等效的applicationDidEnterBackground()或applicationwillenter前台()回调。我使用了一个由@jenzz组合的AppState库。
[AppState]是一个基于RxJava的简单的响应式Android库,用于监控应用程序状态的变化。每当应用程序进入后台并返回前台时,它都会通知订阅者。
事实证明,这正是我所需要的,特别是因为我的应用程序有多个活动,所以简单地检查onStart()或onStop()对一个活动不会削减它。
首先,我将这些依赖项添加到gradle:
dependencies {
compile 'com.jenzz.appstate:appstate:3.0.1'
compile 'com.jenzz.appstate:adapter-rxjava2:3.0.1'
}
然后,将这些行添加到代码中适当的位置就很简单了:
//Note that this uses RxJava 2.x adapter. Check the referenced github site for other ways of using observable
Observable<AppState> appState = RxAppStateMonitor.monitor(myApplication);
//where myApplication is a subclass of android.app.Application
appState.subscribe(new Consumer<AppState>() {
@Override
public void accept(@io.reactivex.annotations.NonNull AppState appState) throws Exception {
switch (appState) {
case FOREGROUND:
Log.i("info","App entered foreground");
break;
case BACKGROUND:
Log.i("info","App entered background");
break;
}
}
});
根据你订阅可观察对象的方式,你可能不得不取消订阅以避免内存泄漏。更多信息再次在github页面。
由于我没有找到任何方法,它也处理旋转而不检查时间戳,我想我也分享我们现在如何在我们的应用程序中这样做。 对这个答案https://stackoverflow.com/a/42679191/5119746唯一的补充是,我们还考虑了方向。
class MyApplication : Application(), Application.ActivityLifecycleCallbacks {
// Members
private var mAppIsInBackground = false
private var mCurrentOrientation: Int? = null
private var mOrientationWasChanged = false
private var mResumed = 0
private var mPaused = 0
然后,对于回调,我们首先有简历:
// ActivityLifecycleCallbacks
override fun onActivityResumed(activity: Activity?) {
mResumed++
if (mAppIsInBackground) {
// !!! App came from background !!! Insert code
mAppIsInBackground = false
}
mOrientationWasChanged = false
}
和onActivityStopped:
override fun onActivityStopped(activity: Activity?) {
if (mResumed == mPaused && !mOrientationWasChanged) {
// !!! App moved to background !!! Insert code
mAppIsInBackground = true
}
然后,这里是附加的:检查方向变化:
override fun onConfigurationChanged(newConfig: Configuration) {
if (newConfig.orientation != mCurrentOrientation) {
mCurrentOrientation = newConfig.orientation
mOrientationWasChanged = true
}
super.onConfigurationChanged(newConfig)
}
就是这样。希望这能帮助到一些人:)
LifecycleObserver已弃用。使用DefaultLifecycleObserver代替:
public class YourApplication extends Application implements DefaultLifecycleObserver {
@Override
public void onCreate() {
super.onCreate();
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
}
@Override
public void onStart(@NonNull LifecycleOwner owner) {
DefaultLifecycleObserver.super.onStart(owner);
}
@Override
public void onResume(@NonNull LifecycleOwner owner) {
DefaultLifecycleObserver.super.onResume(owner);
}
@Override
public void onPause(@NonNull LifecycleOwner owner) {
DefaultLifecycleObserver.super.onPause(owner);
}
@Override
public void onStop(@NonNull LifecycleOwner owner) {
DefaultLifecycleObserver.super.onStop(owner);
}
@Override
public void onDestroy(@NonNull LifecycleOwner owner) {
DefaultLifecycleObserver.super.onDestroy(owner);
}
}
依赖关系:
implementation 'androidx.lifecycle:lifecycle-common:2.5.1'
implementation 'androidx.lifecycle:lifecycle-process:2.5.1'
没有直接的生命周期方法来告诉你整个应用程序何时进入后台或前台。
我用简单的方法做了这件事。按照下面的说明检测应用程序后台/前台阶段。
只要有一点变通办法,这是可能的。在这里,ActivityLifecycleCallbacks可以救场。让我一步一步来。
First, create a class that extends the android.app.Application and implements the ActivityLifecycleCallbacks interface. In the Application.onCreate(), register the callback. public class App extends Application implements Application.ActivityLifecycleCallbacks { @Override public void onCreate() { super.onCreate(); registerActivityLifecycleCallbacks(this); } } Register the “App” class in the Manifest as below, <application android:name=".App". There will be at least one Activity in the started state when the app is in the foreground and there will be no Activity in the started state when the app is in the background. Declare 2 variables as below in the “App” class. private int activityReferences = 0; private boolean isActivityChangingConfigurations = false; activityReferences will keep the count of number of activities in the started state. isActivityChangingConfigurations is a flag to indicate if the current Activity is going through configuration change like an orientation switch. Using the following code you can detect if the App comes foreground. @Override public void onActivityStarted(Activity activity) { if (++activityReferences == 1 && !isActivityChangingConfigurations) { // App enters foreground } } This is how to detect if the App goes background. @Override public void onActivityStopped(Activity activity) { isActivityChangingConfigurations = activity.isChangingConfigurations(); if (--activityReferences == 0 && !isActivityChangingConfigurations) { // App enters background } }
工作原理:
这是按顺序调用Lifecycle方法的一个小技巧。让我来演练一个场景。
假设用户启动了应用程序,启动器活动A被启动。生命周期调用将是,
A.onCreate () A.onStart() (++activityReferences == 1)(应用程序进入前台) A.onResume ()
现在活动A启动活动B。
A.onPause () B.onCreate () B.onStart() (++activityReferences == 2) B.onResume () A.onStop()(——activityReferences == 1)
然后用户从活动B导航回来,
B.onPause () A.onStart() (++activityReferences == 2) A.onResume () B.onStop()(——activityReferences == 1) B.onDestroy ()
然后用户按Home键,
A.onPause () A.onStop()(——activityReferences == 0)(应用程序进入后台)
在这种情况下,如果用户从活动B按Home键而不是后退键,它仍然是一样的,activityReferences将是0。因此,我们可以检测作为应用程序进入后台。
那么,isActivityChangingConfigurations的角色是什么?在上面的场景中,假设活动B改变了方向。回调序列将是,
B.onPause () B.onStop()(——activityReferences == 0)(应用程序进入后台??) B.onDestroy () B.onCreate () B.onStart() (++activityReferences == 1)(应用程序进入前台??) B.onResume ()
这就是为什么我们有一个额外的isActivityChangingConfigurations检查,以避免活动正在经历配置更改的场景。
推荐文章
- 警告: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文件