检测应用程序是否已手动关闭

时间:2015-01-16 22:29:24

标签: android broadcastreceiver

我已经编写了一个Android应用程序,它通过使用BroadcastReceiver继承的类来检查网络状态:

public class NetworkChangeReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(final Context context, final Intent intent) {
        Log.d("mylog", "NetworkChangeReceiver Hit");
    }
}

在清单文件中注册,如下所示:

<receiver
    android:name="foo.NetworkChangeReceiver"
    android:label="NetworkChangeReceiver" >
    <intent-filter>
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
        <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
    </intent-filter>
</receiver>

我需要在连接或断开连接时处理互联网连接。实际上,它在正常情况下完美运行。

但问题是,当手动关闭应用程序时(通过最小化应用程序然后通过在最近按钮菜单中滑动应用程序图标来关闭它),它仍然会收到网络状态更改。这有时会导致一些例外。

即使我在try / catch块中包含了接收器函数中的所有代码,但有时仍会显示包含错误消息的Toast消息。即使在应用程序关闭几天后,有时也会发生这种情况。

请注意,接收函数中的代码比此处显示的代码更复杂,并且可以访问内部类和变量。

3 个答案:

答案 0 :(得分:2)

即使您的应用未运行,您的应用仍会收到事件。在onReceive()中执行任何操作之前,您可以通过以下方式检查活动是否正在运行:

选项1:在您的活动中使用静态变量来检查接收者访问的状态:

public class YourActivity extends Activity {


 public static boolean isRunning = false;

 @Overrride
 public void onCreate(Bundle savedInstanceState){
 isRunning = true;
  ....
 }
   //We need receiver to work when app is minimized
   /*
      @Override
      public void onStart() {
         super.onStart();
         isRunning = true;
      } 


      @Override
      public void onStop() {
         super.onStop();
         isRunning = false;
      }
*/

}

在接收器中:

public class NetworkChangeReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(final Context context, final Intent intent) {
        Log.d("mylog", "NetworkChangeReceiver Hit");
            if(!YourActivity.isRunning)
              return;
    }
}

选项2 :使用ActivityManager

public class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, final Intent intent) {

    if (isAppForground(context)) 
         return;

}

public boolean isAppForground(Context mContext) {

    ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
    List<RunningTaskInfo> tasks = am.getRunningTasks(1);
    if (!tasks.isEmpty()) {
        ComponentName topActivity = tasks.get(0).topActivity;
        if (!topActivity.getPackageName().equals(mContext.getPackageName())) {
            return false;
        }
    }

    return true;
}

}

您需要获得许可:

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

答案 1 :(得分:1)

如果您在清单中定义接收器,则应用程序将接收事件,即使它未启动也是如此。

http://developer.android.com/guide/topics/manifest/receiver-element.html

  

广播接收器使应用程序能够接收由系统或其他应用程序广播的意图,即使应用程序的其他组件未运行也是如此。

要解决此问题,请不要在清单中定义Receiver,而是在onStart中以编程方式执行,然后在onStop中再次注销。此解决方案的问题在于,如果您的应用处于后台,则无法收到消息。

private BroadcastReceiver receiver;

@Overrride
public void onStart(){

   super.onStart();

   IntentFilter filter = new IntentFilter();
   filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
   filter.addAction("android.net.wifi.WIFI_STATE_CHANGED");

   receiver = new NetworkChangeReceiver();
   registerReceiver(receiver, filter);
}

@Override
protected void onStop() {
   super.onStop();
   //don't forget to unregister the receiver again
   unregisterReceiver(receiver);
}

编辑:onCreateonDestroy无法正常工作,因为在应用关闭的每个实例中都不会调用onDestroy(例如,如果它被任务管理器关闭) )

答案 2 :(得分:0)

找到解决方案:

我找到了解决问题的完美方案。感谢Android service crashes after app is swiped out of the recent apps list中的正确答案,我发现当应用程序通过“最近”列表关闭时,将再次创建整个过程,并且所有静态变量将刷新为其默认值,并且onCreate和all其他方法不会被调用。 所以解决方案就像:

public static boolean appStarted = false;
protected void onCreate(Bundle savedInstanceState) {
    appStarted = true;
    ...
}


public class NetworkChangeReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(final Context context, final Intent intent) {
        if (!MyActivity.appStarted)
            return;
        ...
    }
}

关键是要跟踪应用程序何时启动,而不是应用程序关闭时(因为应用程序的关闭事件不可靠,在某些情况下无法正常工作)