我试图写一个应用程序,做一些具体的时候,它被带回前台后一段时间。是否有一种方法可以检测应用程序是被发送到后台还是被带到前台?
当前回答
这是@d60402回答的修改版本:https://stackoverflow.com/a/15573121/4747587
按照上面提到的去做。但是,与其有一个Base Activity,并将其作为每个活动的父活动,并重写onResume()和onPause,不如执行以下操作:
在你的应用程序类中,添加这样一行:
registerActivityLifecycleCallbacks(应用程序。ActivityLifecycleCallbacks回调);
这个回调有所有的活动生命周期方法,你现在可以覆盖onactivityresume()和onActivityPaused()。
看看这个Gist: https://gist.github.com/thsaravana/1fa576b6af9fc8fff20acfb2ac79fa1b
其他回答
The principal problem is that you have to get an specific behavior when you start an activity from background. If you override your onPause() and onResume() methods, you'll have a close answer, but not the solution. The problem is that onPause() and onResume() methods are called even if you don't minimize your application, they can be called when you start an activity and later you press the back button to return to your activity. To eliminate that problem and to know really when your application comes from background, you must to get the running process and compare with your process:
private boolean isApplicationBroughtToBackground() {
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> tasks = am.getRunningTasks(1);
if (!tasks.isEmpty()) {
ComponentName topActivity = tasks.get(0).topActivity;
if (!topActivity.getPackageName().equals(getPackageName())) {
return true;
}
}
return false;
}
现在你必须声明一个布尔变量:
public boolean wasPaused = false;
并询问你的活动何时进入后台:
@Override
public void onPause(){
super.onPause();
if(isApplicationBroughtToBackground())
wasPaused = true;
}
现在,当你的活动再次出现在屏幕上时,在onResume()方法中询问:
@Override
public void onResume(){
super.onResume();
if(wasPaused){
lockScreen(true);
}
wasPaused = false;
}
就是这样。现在,当您的活动进入后台,稍后用户将其带到前台时,锁定屏幕将出现。
如果你想为你的应用程序的任何活动重复这个行为,你必须创建一个活动(可以是BaseActivity),放这个方法,你所有的活动都必须从BaseActivity继承。
我希望这对你有帮助。
问候!
我发现了一个很好的方法来检测应用程序是否进入前台或后台。 这是我的代码。 希望这对你有帮助。
/**
* Custom Application which can detect application state of whether it enter
* background or enter foreground.
*
* @reference http://www.vardhan-justlikethat.blogspot.sg/2014/02/android-solution-to-detect-when-android.html
*/
public abstract class StatusApplication extends Application implements ActivityLifecycleCallbacks {
public static final int STATE_UNKNOWN = 0x00;
public static final int STATE_CREATED = 0x01;
public static final int STATE_STARTED = 0x02;
public static final int STATE_RESUMED = 0x03;
public static final int STATE_PAUSED = 0x04;
public static final int STATE_STOPPED = 0x05;
public static final int STATE_DESTROYED = 0x06;
private static final int FLAG_STATE_FOREGROUND = -1;
private static final int FLAG_STATE_BACKGROUND = -2;
private int mCurrentState = STATE_UNKNOWN;
private int mStateFlag = FLAG_STATE_BACKGROUND;
@Override
public void onCreate() {
super.onCreate();
mCurrentState = STATE_UNKNOWN;
registerActivityLifecycleCallbacks(this);
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
// mCurrentState = STATE_CREATED;
}
@Override
public void onActivityStarted(Activity activity) {
if (mCurrentState == STATE_UNKNOWN || mCurrentState == STATE_STOPPED) {
if (mStateFlag == FLAG_STATE_BACKGROUND) {
applicationWillEnterForeground();
mStateFlag = FLAG_STATE_FOREGROUND;
}
}
mCurrentState = STATE_STARTED;
}
@Override
public void onActivityResumed(Activity activity) {
mCurrentState = STATE_RESUMED;
}
@Override
public void onActivityPaused(Activity activity) {
mCurrentState = STATE_PAUSED;
}
@Override
public void onActivityStopped(Activity activity) {
mCurrentState = STATE_STOPPED;
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
mCurrentState = STATE_DESTROYED;
}
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
if (mCurrentState == STATE_STOPPED && level >= TRIM_MEMORY_UI_HIDDEN) {
if (mStateFlag == FLAG_STATE_FOREGROUND) {
applicationDidEnterBackground();
mStateFlag = FLAG_STATE_BACKGROUND;
}
}else if (mCurrentState == STATE_DESTROYED && level >= TRIM_MEMORY_UI_HIDDEN) {
if (mStateFlag == FLAG_STATE_FOREGROUND) {
applicationDidDestroyed();
mStateFlag = FLAG_STATE_BACKGROUND;
}
}
}
/**
* The method be called when the application been destroyed. But when the
* device screen off,this method will not invoked.
*/
protected abstract void applicationDidDestroyed();
/**
* The method be called when the application enter background. But when the
* device screen off,this method will not invoked.
*/
protected abstract void applicationDidEnterBackground();
/**
* The method be called when the application enter foreground.
*/
protected abstract void applicationWillEnterForeground();
}
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()上被调用,在应用程序扩展类中-转向不必要调用活动中的方法。 希望能有所帮助。
没有直接的生命周期方法来告诉你整个应用程序何时进入后台或前台。
我用简单的方法做了这件事。按照下面的说明检测应用程序后台/前台阶段。
只要有一点变通办法,这是可能的。在这里,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检查,以避免活动正在经历配置更改的场景。
我们可以使用LiveData扩展这个解决方案:
class AppForegroundStateLiveData : LiveData<AppForegroundStateLiveData.State>() {
private var lifecycleListener: LifecycleObserver? = null
override fun onActive() {
super.onActive()
lifecycleListener = AppLifecycleListener().also {
ProcessLifecycleOwner.get().lifecycle.addObserver(it)
}
}
override fun onInactive() {
super.onInactive()
lifecycleListener?.let {
this.lifecycleListener = null
ProcessLifecycleOwner.get().lifecycle.removeObserver(it)
}
}
internal inner class AppLifecycleListener : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onMoveToForeground() {
value = State.FOREGROUND
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onMoveToBackground() {
value = State.BACKGROUND
}
}
enum class State {
FOREGROUND, BACKGROUND
}
}
现在我们可以订阅这个LiveData并捕获所需的事件。例如:
appForegroundStateLiveData.observeForever { state ->
when(state) {
AppForegroundStateLiveData.State.FOREGROUND -> { /* app move to foreground */ }
AppForegroundStateLiveData.State.BACKGROUND -> { /* app move to background */ }
}
}
推荐文章
- 警告: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文件