【问题标题】:Discovering if Android activity is running发现 Android 活动是否正在运行
【发布时间】:2012-05-27 05:33:06
【问题描述】:

我正在使用 C2DM,我的 BroadcastReceivers 将 C2DM 事件传播到本地服务。该服务通过将 id 发送到我的网络服务器 pus 来完成注册,它负责让设备知道新消息,但是如果应用程序(其中一个活动)启动,我们希望使用新数据向该活动发送一个意图,所以它可以被更新,如果不是 NotificationManager 用于通知用户。

问题是,如何知道活动正在运行?应用程序对象不是一个选项,因为服务是应用程序的一部分,它显然会出现。在每个应用程序的 onDesroy 中取消注册也不是一个选项,因为它可能发生在方向更改中......

有什么标准的方法来完成它吗?

【问题讨论】:

    标签: android android-activity android-c2dm


    【解决方案1】:

    解决方案 1: 您可以使用 ActivityManager 检查 Activity 是否正在运行:

    public boolean isActivityRunning() { 
    
    ActivityManager activityManager = (ActivityManager)Monitor.this.getSystemService (Context.ACTIVITY_SERVICE); 
        List<RunningTaskInfo> activitys = activityManager.getRunningTasks(Integer.MAX_VALUE); 
        isActivityFound = false; 
        for (int i = 0; i < activitys.size(); i++) { 
            if (activitys.get(i).topActivity.toString().equalsIgnoreCase("ComponentInfo{com.example.testapp/com.example.testapp.Your_Activity_Name}")) {
                isActivityFound = true;
            }
        } 
        return isActivityFound; 
    } 
    

    需要将权限添加到您的清单..

    <uses-permission  android:name="android.permission.GET_TASKS"/>
    

    解决方案 2: 您可以在要检查它是否正在运行的活动中使用静态变量,并将其存储在某个位置以便从您的服务或广播接收器访问:

    static boolean CurrentlyRunning= false;
          public void onStart() {
             CurrentlyRunning= true; //Store status of Activity somewhere like in shared //preference 
          } 
          public void onStop() {
             CurrentlyRunning= false;//Store status of Activity somewhere like in shared //preference 
          }
    

    我希望这会有所帮助!

    【讨论】:

    • 第一种方法看起来很有趣,但我想知道是否有任何活动正在运行,或者更像是我的应用程序是否正在运行(不包括服务)静态方法操作系统不好,因为活动可能有多个实例也许应用程序互斥锁可以解决问题......
    • 我可能错了,但我认为这只会检查任务中当前的顶级活动。如果是这样,同一任务中的其他活动(暂停或停止)呢?
    • 不要使用第一种方法。来自 ActivityManager 文档:“注意:此方法仅用于调试和呈现任务管理用户界面。绝不应将其用于应用程序中的核心逻辑,例如根据此处找到的信息决定不同的行为。”
    • 另外,它现在已被弃用和损坏:@deprecated As of LOLLIPOP, this method * is no longer available to third party * applications: the introduction of document-centric recents means * it can leak person information to the caller. For backwards compatibility, * it will still return a small subset of its data: at least the caller's * own tasks, and possibly some other tasks * such as home that are known to not be sensitive
    • 当您运行 BroadcastReceiver / Service 时,解决方案 1 不起作用。该应用程序似乎始终在运行。但是,在尝试了无数其他方法之后,解决方案 2 对我们非常有效。
    【解决方案2】:

    如果您想通过您的活动(如果有任何正在运行)来处理传入的 Google Cloud 消息 (C2DM),或者如果没有活动正在运行,则发出通知,则下一种方法会很有效。

    在清单文件中注册一个 BroadcastReceiver。每当应用程序未运行时,此接收器将处理 C2D 消息。在您的活动中以编程方式注册另一个 BroadcastReceiver。该接收器将在活动运行时处理 C2D 消息。

    AndoroidManifest.xml

    <receiver
        android:name=".StaticReceiver"
        android:permission="com.google.android.c2dm.permission.SEND" >
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <category android:name="com.mypackage" />
        </intent-filter>
    </receiver>
    

    MyReceiver.java

    public class StaticReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            // TODO Trigger a Notification
        }
    }
    

    MyActivity.java

    public class MyActivity extends ActionBarActivity {
    
        @Override
        protected void onResume() {
        super.onResume();
    
            final IntentFilter filter = new 
                    IntentFilter("com.google.android.c2dm.intent.RECEIVE");
            filter.addCategory("com.mypackage");
            filter.setPriority(1); 
            registerReceiver(dynamicReceiver, filter, 
                    "com.google.android.c2dm.permission.SEND", null);
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            unregisterReceiver(dynamicReceiver);
        }
    
        private final BroadcastReceiver dynamicReceiver 
                = new BroadcastReceiver() 
        {
            @Override
            public void onReceive(Context context, Intent intent) {
    
                // TODO Handle C2DM
    
                // blocks passing broadcast to StaticReceiver instance
                abortBroadcast();
           }
        };
    }
    

    注意!要先捕获广播,dynamicReceiver IntentFilter 的优先级必须高于 StaticReceiver 实例 IntentFilter 的优先级(默认优先级为 '0')。

    PS。看起来 Google Cloud Messaging Service 发出的广播是有序广播。原创创意作者:CommonsWare

    【讨论】:

      【解决方案3】:

      复制自here

      您可以在活动中使用静态变量。

      class MyActivity extends Activity {
           static boolean active = false;
      
            public void onStart() {
               active = true;
            } 
      
            public void onStop() {
               active = false;
            }
      }
      

      【讨论】:

      • 如果您在另一个问题及其答案中找到了完美匹配,您不应该在这里回答,而是将此问题标记为重复...
      【解决方案4】:

      检查 Activity 是否正在运行的最简单方法是:

      Context context = MyActivity.this; 
      
      if (! ((Activity) context).isFinishing()) {
          //  Activity is running
      } else {
          //  Activity has been finished
      }
      

      注意:如果活动未运行,则不应执行任何与 UI 相关的操作。

      【讨论】:

      • 当从后台服务发出时,Context context = MyActivity.this; 将导致错误提示 MyActivity“不是封闭类”
      • 好吧,如果您已经持有MyActivity.this,那么无论如何都有更好/更简单的方法来检查活动状态:D
      猜你喜欢
      • 1970-01-01
      • 2011-07-23
      • 2015-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多