Android 应用、活动状态(运行、未运行、前台/后台)
Posted
技术标签:
【中文标题】Android 应用、活动状态(运行、未运行、前台/后台)【英文标题】:Android App, Activity State (Running, Not Running, Foreground/ Background) 【发布时间】:2015-08-16 02:32:24 【问题描述】:我遇到了一个需求,但我无法获得正确的实施方式,因此需要您的帮助。
我想做什么? - 我想根据收到的通知执行如下操作:
-
当应用程序打开并处于前台即用户可见并且我收到通知时,我只需显示一个弹出窗口来启动我的 Activity B
当应用程序关闭时,即既不在后台也不在前台,我收到通知我将首先启动我的应用程序,然后启动 Activity B
当应用程序在后台运行但在最近运行但对用户不可见时,我想在不重新启动应用程序的情况下启动我的 Activity B。此外,在这种情况下,当用户按下 Activity B 时,他们应该会在将其发送到后台之前看到他们离开的屏幕。
我做了什么? 我已经达到了第 1 点和第 2 点。我想达到第 3 点。我已经尝试了以下
public static boolean isApplicationBroughtToBackground(final Activity activity)
ActivityManager activityManager = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> tasks = activityManager.getRunningTasks(1);
// Check the top Activity against the list of Activities contained in the Application's package.
if (!tasks.isEmpty())
ComponentName topActivity = tasks.get(0).topActivity;
try
PackageInfo pi = activity.getPackageManager().getPackageInfo(activity.getPackageName(), PackageManager.GET_ACTIVITIES);
for (ActivityInfo activityInfo : pi.activities)
if(topActivity.getClassName().equals(activityInfo.name))
return false;
catch( PackageManager.NameNotFoundException e)
return false; // Never happens.
return true;
但是,这在两种情况下都返回 true,点 #2 和 #3,所以我无法仅区分 #3。
我在每个活动中都尝试了以下内容,
@Override
protected void onPause()
super.onPause();
saveIsPausedInPref(true);
@Override
protected void onResume()
super.onResume();
saveIsPausedInPref(false);
但是,如果通过按主页按钮将应用程序发送到后台,我的首选项将具有 isPaused = true 并且如果用户从最近删除应用程序,它也不会给出所需的结果那么它将保持真实,当通知到达时,我将无法区分第 2 点和第 3 点。
为整个故事道歉,但我希望我能够解释我的要求。
提前致谢。 :)
编辑:
<activity
android:name=".HomeActivity"
android:screenOrientation="portrait" >
</activity>
<activity
android:name=".ChatProfileActivity"
android:screenOrientation="portrait" >
</activity>
【问题讨论】:
据我所知,当用户按下 Activity 3 上的back
按钮时,您需要切换到前台的应用程序?
是的,如果这是一种可能的方式。理想情况下,我需要从后台调用我的应用程序并在其上启动我的 Activity B。
显示您的清单文件,我想查看 Activity A 和 B 声明。
@MurtazaKhursheedHussain - 请查看我的编辑。我猜那里没什么特别的。
【参考方案1】:
下面的代码对我有用
在 AndroidManifest.xml
中<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:name=".MyApplication"
>
MyApplication.java
public class MyApplication extends Application
private ActivityLifecycleCallbacks myLifecycleHandler;
@Override
public void onCreate()
super.onCreate();
myLifecycleHandler=new MyLifecycleHandler();
registerActivityLifecycleCallbacks(myLifecycleHandler);
MyLifecycleHandler.java
public class MyLifecycleHandler implements Application.ActivityLifecycleCallbacks
private static final String TAG = MyLifecycleHandler.class.getSimpleName();
private static int resumed;
private static int paused;
private static int started;
private static int stopped;
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState)
@Override
public void onActivityDestroyed(Activity activity)
@Override
public void onActivityResumed(Activity activity)
++resumed;
@Override
public void onActivityPaused(Activity activity)
++paused;
Log.d(TAG, "application is in foreground: " + (resumed > paused));
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState)
@Override
public void onActivityStarted(Activity activity)
++started;
@Override
public void onActivityStopped(Activity activity)
++stopped;
Log.d(TAG, "application is visible: " + (started > stopped));
public static boolean isApplicationVisible()
return started > stopped;
public static boolean isApplicationInForeground()
return resumed > paused;
现在使用 myLifecycleHandler 方法,您可以获得所需的所有状态。
isApplicationInForeground 表示 -> 至少一个活动处于可见状态。
isApplicationVisible 表示 -> 至少有一个活动已启动但未停止,表示应用程序处于运行状态
如果 isApplicationInForeground 为真 isApplicationVisible 将始终为真,反之则不为真
【讨论】:
isApplicationVisible 和 isApplicationInForeground 有什么区别?【参考方案2】:要区分案例 #2 和案例 #3,您可以执行以下操作:
如果不是 case #1,则启动 ActivityB
。在ActivityB.onCreate()
中这样做:
super.onCreate(...);
if (isTaskRoot())
// ActivityB has been started when the app is not running,
// start the app from the beginning
Intent restartIntent = new Intent(this, MyRootActivity.class);
startActivity(restartIntent);
finish();
return;
... rest of onCreate() code here...
【讨论】:
谢谢大卫,我现在才用这个。 :) 正在寻找更好的答案。直到我发现会坚持下去。 “更好的答案”是什么意思。这有什么问题?也许你的架构被破坏了,因为你试图区分所有这些情况。你到底想要达到什么目的?【参考方案3】:我知道你想出了 1 和 2,但我自己的想法不对,以防你做了其他事情,你想看看。
如何知道你的应用是否在前台?
this 应该是正确的方式,如果它在前台然后发布一个事件 通过eventbus,事件总线是 我喜欢的方式。
在具有堆栈的特定活动中启动应用程序? 看一眼 TaskStackBuilder 有了这个 answer, 它将提供如何正确执行此操作的信息。 在保留当前堆栈的同时恢复具有特定活动的应用程序? 使用回调检查应用程序的状态,然后在收到通知时打开活动没有 FLAG_ACTIVITY_NEW_TASK。这应该是 tricl。【讨论】:
能否请您强调一下“使用回调检查应用程序的状态”? 在活动回调中检查它是否命中 onActivityPaused 而不是 onActivityDestroyd。这将使您能够了解您的应用程序的状态。 好吧。我会试一试。 :) 谢谢【参考方案4】:如果您更改为不显示任何弹出窗口,只是为了始终转到 Activity B(已销毁、后台或前台),则不需要任何此检查。 只是为了在您的通知上使用标志 FLAG_ACTIVITY_X(它是 GCM 这个通知?)。
LaunchMode on Manifest
Intent Flags
您可以使用 onNewIntent 方法检查 Intent 是否来自通知并启动 Activity B。
Notification Proper BackStack
【讨论】:
以上是关于Android 应用、活动状态(运行、未运行、前台/后台)的主要内容,如果未能解决你的问题,请参考以下文章
当应用程序未在 Android 上运行时,使用 React Native 在状态栏上显示通知图标