发现 Android 活动是不是正在运行

Posted

技术标签:

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

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

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

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

【问题讨论】:

【参考方案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("ComponentInfocom.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

以上是关于发现 Android 活动是不是正在运行的主要内容,如果未能解决你的问题,请参考以下文章

如何确定 Skype 通话当前是不是在 Android 上处于活动状态

视图隐藏在android活动中的其他视图后面

Android:同时进行两个活动

另一个活动的Android意图被多次执行

Android进程经常产生logcat“已死亡”消息。

在 Android 中,启动活动对结果有啥用? [复制]