【问题标题】:Check when my app is in background when back-button and home-button当返回按钮和主页按钮时检查我的应用程序何时在后台
【发布时间】:2012-03-29 10:48:45
【问题描述】:

大家好,我正在使用这种方法来检查我的应用是否在后台:

public static boolean isApplicationSentToBackground(final Context context) {
    ActivityManager am = (ActivityManager) context
            .getSystemService(Context.ACTIVITY_SERVICE);
    List<RunningTaskInfo> tasks = am.getRunningTasks(1);
    for( RunningTaskInfo rti: tasks ) {
        ComponentName cn = rti.topActivity;
        LogHelper.i(TAG, "Component Name: " + cn.getPackageName() );
    }



    if (!tasks.isEmpty()) {
        ComponentName topActivity = tasks.get(0).topActivity;
        if (!topActivity.getPackageName().equals(context.getPackageName())) {
            return true;
        }
    }

    return false;
}

我在我的 Activity onPause、onStop、onDestroy 中调用此方法 这是我的结果:

当我在我的活动中并单击 android-home-button 时,它遵循以下流程:

onPause -> 在后台?真的 onStop -> 在后台?真的

这一切都很完美。 问题是当我单击 android-back-button 时,活动会返回到 android 主页。这是流程:

onPause -> 在后台?错误的 onStop -> 在后台?错误的 onDestroy -> 在后台?假的

如果您检查代码,我有一个 Log cat 标记,它总是(在后退按钮的情况下)标记这个:

03-29 00:46:39.324:I/DFFramework(15344):MusicUtils - 组件名称:my-activity-name

这意味着我的活动不在后台。 我能做什么?

更新:

我正在添加有关我的场景的更多信息。我正在开发一个音乐播放器,所以如果应用程序关闭但音乐仍在播放(否则音乐将暂停),我必须捕捉这种事件以启动我的前台音频服务。 所以我必须捕捉应用程序何时处于后台(例如当您单击 android-home-button 时)或当您关闭应用程序时(例如当您单击 android-back-button 时)。

【问题讨论】:

    标签: android


    【解决方案1】:

    这就是我解决的方法(模拟 Google 音乐播放器的行为)

    正如我所说,我正在寻找两种事件:

    • 当我的应用进入后台时

    • 当用户点击 androd-back-button 并进入 android 主页时(应用程序被破坏)

    所以这是我在超级活动中完成的 onPause

    @Override
        protected void onPause() {
            boolean bg = MusicUtils.isApplicationSentToBackground(this);
            if ( bg ) {
                MusicUtils.startForegroundMusic(this);
            } else {
                if ( isBackPressed ) {
                    //MusicUtils.getActiviesApplicationInBackStack(this) <= 1
                    if ( isBackPressed && (this instanceof DashBoardActivity || MusicUtils.getActiviesApplicationInBackStack(this) <= 1) ) {
                        MusicUtils.startForegroundMusic(this);
                    }
                }
            }
            super.onPause();
        }
    

    首先,我使用 isApplicationSentToBackground(问题正文中的源代码)检查应用程序是否在后台。

    如果应用不在后台,有两个原因:

    • 活动仍在前台,因此调用 onPause 是因为我们正在开始一个新活动或我们正在改变方向(我需要跳过此事件)
    • 应用程序将被销毁(活动也是如此),我需要捕获此事件才能启动前台音乐

    所以为了捕捉第二个事件,我检查用户是否按下了返回按钮

    private boolean isBackPressed = false;
    
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                LogHelper.i(TAG, "BACK PRESSED EVENT");
                isBackPressed = true;
            }
    
            // Call super code so we dont limit default interaction
            return super.onKeyDown(keyCode, event);
        }
    

    如果他们按下了 bakc 键,我会检查这个活动是否是最新的(所以在当前活动被销毁后,我的应用程序将被销毁!)

    为了检查这个,我得到了 MusicUtils.getActiviesApplicationInBackStack(this) 返回的计数

        public static int getActiviesApplicationInBackStack(final Context context) {
        int count = 0;
        ActivityManager am = (ActivityManager) context.getSystemService( Context.ACTIVITY_SERVICE );
        List<RunningTaskInfo> runningTaskInfoList =  am.getRunningTasks(10);
        Iterator<RunningTaskInfo> itr = runningTaskInfoList.iterator();
        while(itr.hasNext()){
            RunningTaskInfo runningTaskInfo = (RunningTaskInfo)itr.next();
            if ( runningTaskInfo.topActivity.getPackageName().equals(context.getPackageName()) ) {
                count += runningTaskInfo.numActivities;
            }
        }
        return count;
    }
    

    我希望这个答案能帮助解决我同样问题的人 :) 我知道这是一个奇怪的场景,但分享问题、想法和代码总是一个好主意 :)

    【讨论】:

      【解决方案2】:

      你为什么想要那个? “在后台”对您意味着什么?从活动的角度来看,您的应用要么处于活动状态(例如已调用 OnResume),要么已暂停(已调用 OnPaused),要么已死(已调用 OnDestroy)。

      在暂停状态下,您通常不应该做任何工作。您的应用已暂停,为需要系统资源的不同应用让路。

      如果您需要确保某些东西在后台运行,那么您很可能需要一个服务,尽管使用在后台运行很长时间的服务通常是不好的形式,除非您正在构建类似的东西例如音乐播放器。

      因此,根据您的评论,您正在构建一个音乐播放器。现在音乐播放器有两种模式:

      1. 在播放音乐时用户正在与之交互
      2. 背景音乐正在播放。

      使用音乐播放服务是有意义的,这样它就可以独立于控制音乐播放器的任务(活动)运行。当用户回击时,Activity 将被销毁,当用户点击 Home 按钮、接听电话、锁定屏幕等时,Activity 将暂停。

      现在很容易检测到这些情况。如果活动被暂停,这意味着用户正在做其他事情。然后,您应该确保您的音乐继续播放。 Android为此提供了startForeground,这意味着系统只会在万不得已的情况下杀死它。因此,在您的活动的 OnPause 上,您应该通知服务并将其置于前台模式,这也会显示通知。

      当用户从 OnDestroy 完成您的活动时,您也可以这样做。

      剩下的就是确保在 OnResume 中再次启动您的活动时调用 stopForeground。

      我建议您阅读 Android 架构,了解不同组件和生命周期的工作原理。同样,应该有理由以您现在尝试的方式检查您的应用是否处于“后台”。

      【讨论】:

      • 好问题 botteaap 。我正在开发音乐播放器,并且正在尝试遵循 Google 音乐模式。当您播放歌曲并且您在应用程序中时,Google 音乐不会显​​示已播放歌曲的通知。当您单击主页按钮(谷歌音乐应用程序在后台)时,它会显示通知。我已经这样做了,但是当您单击后退按钮并返回到 android 主屏幕时,问题仍然存在。在这种情况下,如您所见,我的应用程序不会进入后台...
      • 我已经编辑了我的答案,希望对您有所帮助。您还可以查看音乐应用的 Android 源代码,看看他们是如何做到的。
      • botteaap 我已经将音乐播放器的源代码用作操场/学习,事实上一切正常。但是andoid音乐播放器(旧的)在播放歌曲时启动通知,而不是在播放歌曲并且应用程序处于后台时启动通知,这是对资源和时间的巨大浪费。正如我所说,我已经使用该方法检查了我的 onPause 并且当您单击主页按钮时它正在工作,但是 onPause 和 onDestroy 总是在活动被破坏时被调用,并且当您返回或当您遍历您的活动时,活动被破坏应用里面。
      • [CONTINUE] 所以我的问题是:我必须知道是否在 onDestroy 中(仅当您返回并退出应用程序时调用)我的应用程序正在后台运行,因为如果我在onDestroy 和我的应用程序不在后台,这是因为我要进入我的应用程序并打开另一个活动。
      • Activity 没有“在后台”的概念,无论您的用户是否与您的 Activity 交互。当您的应用程序点击 OnPause 时,它​​可能会暂停并在后台运行,并且它也可能在不久之后被杀死并且永远不会回来。如果 Activity 终止或刚刚暂停,isFinishing 方法将为您提供 onPause。但即使在那种情况下,它也可能在以后被销毁。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-26
      • 1970-01-01
      • 2020-10-12
      相关资源
      最近更新 更多