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

Detect if the application is manually closed or not

我写了一个 android 应用程序,它使用继承的 BroadcastReceiver 检查网络状态 class:

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 消息。即使在应用程序关闭几天后,有时也会发生这种情况。

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

如果您在清单中定义接收器,应用程序将接收事件,即使它没有启动。

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

Broadcast receivers enable applications to receive intents that are broadcast by the system or by other applications, even when other components of the application are not running.

要解决此问题,只需不要在清单中定义 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 不会在应用程序关闭的每个实例中调用(例如,如果使用任务管理器关闭它)

您的应用仍会接收事件,即使它不是 运行。在 onReceive() 中执行任何操作之前,您可以通过以下方式检查 activity 是否为 运行:

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

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" />

找到的解决方案:

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

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;
        ...
    }
}

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