为什么BroadcastReceiver即使应用程序处于后台也能正常工作?

Yog*_*ani 19 android manifest broadcastreceiver

我正在使用BroadcastReceiver检查我的应用程序中的Internet连接,如果连接丢失,我会显示一个警告对话框.它工作正常.但我的问题是,即使我的应用程序在背景幕中,BroadcastReceiver也能正常工作.因此,即使用户在其他应用程序中,当互联网连接丢失时,对话框也会弹出.这完全破坏了我的应用程序.

有没有人知道如何限制应用程序中的广播接收器?

这是我的BroadcastReceiver:

 public class ConnectivityChangedReceiver extends BroadcastReceiver{

    @Override
    public void onReceive( Context context, Intent intent )
     {
        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService( Context.CONNECTIVITY_SERVICE );
    NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
    if (networkInfo != null && networkInfo.isConnected()) {
    } else {
        try{
            Intent i=new Intent(context, InternetDialogActivity.class);
            i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(i);
        } catch(Exception e){
            e.printStackTrace();
        }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

活动是:

 public class InternetDialogActivity extends Activity implements OnClickListener{
   @Override
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.internet_dialog_box);
      getWindow().setLayout(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
      Button retryButton = (Button) findViewById(R.id.retryInternetButton);
      retryButton.setOnClickListener(this);
    }

   public boolean checkConnectivity(){
       ConnectivityManager connectivityManager   = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
           NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();

       if (networkInfo!=null && networkInfo.isConnected()) {
           finish();
           return true;
       } else {
           Intent intent = getIntent();
           finish();
           startActivity(intent);
           return false; 
      }
   }

   @Override
   public void onClick(View view) {
      switch(view.getId()){
         case R.id.retryInternetButton:
             try{
                 checkConnectivity();
             } catch(Exception e){
                 e.printStackTrace();
             }
             break;
       }
   }
   }
Run Code Online (Sandbox Code Playgroud)

以下是我在清单中声明接收器和活动的方式:

  <receiver android:name="com.lisnx.service.ConnectivityChangedReceiver"
        android:label="NetworkConnection">
        <intent-filter>
            <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
        </intent-filter>
  </receiver>

  <activity android:name="com.lisnx.activity.InternetDialogActivity"
        android:configChanges="orientation|keyboardHidden"
        android:theme="@android:style/Theme.Dialog" />
Run Code Online (Sandbox Code Playgroud)

我已经读过,我们可以通过不在清单中声明它来限制BroadcastReceiver在应用程序内工作.但我不知道接收器将如何工作呢?请帮我.我被严重困扰了.Thanx提前.

Eri*_*ric 37

BroadcastReceiver当应用程序处于后台时,A 可以正常工作,因为接收方接收的事件是全局发送的,并且每个应用程序都已注册以监听这些应用程序,无论它是否正在运行.

要解决这个问题,请在您BroadcastReceiveronReceive代码中检查您的应用是否位于前台.

我知道有一个 - 也是唯一一个 - 持续有效的方法来做到这一点.您需要跟踪应用程序的暂停/恢复操作.确保在每项活动中检查此项.

这个答案中有一些示例代码(解决方案#1).在您的情况下,您可以MyApplication.isActivityVisible() == true在做任何事情之前检查作为验证BroadcastReceiver.

  • 这不是最佳解决方案.最佳解决方案是在主活动(或您想要的活动)中调用BroadcastReceiver,而不是在android清单文件中声明它.在应用程序内而不是清单中创建广播接收器允许应用程序仅在运行时处理分离的事件.这样,分离的事件仅发送到当前正在运行的应用程序,而不是广播到所有应用程序. (8认同)

小智 17

您是否尝试从清单中删除Intent过滤器并在活动中注册/取消注册?因此,您可以尝试在onStart()中注册Intent过滤器,并在onStop()方法上注销它.代码有点像这样:

static final String ACTION = "android.net.conn.CONNECTIVITY_CHANGE";


IntentFilter filter = new IntentFilter(ACTION);
this.registerReceiver(ConnectivityChangedReceiver, filter);


unregisterReceiver(ConnectivityChangedReceiver);
Run Code Online (Sandbox Code Playgroud)

如果还不熟悉,您还应该了解Activity Lifecycle.

  • +1我认为这是解决OP问题的最佳方法(虽然我会在`onPause()`和`onResume()`而不是`onStop()`和`onStart()`中进行.是的,它可以在每个活动中完成,但你可以通过创建自己的`BaseActivity`来扩展`Activity`并覆盖`onPause()`和`onResume()`以及注册/取消注册你的接收器.只需让你的所有活动扩展`BaseActivity()`并让他们像往常一样调用`super.onResume()`和`super.onPause()`. (3认同)

Dav*_*ser 13

您应注册/注销您BroadcastReceiveronPause()onResume()每个活动的.然后你知道当你的应用程序在前台时,接收器只是"监听".您可以轻松地做到这一点通过创建自己的BaseActivity延伸Activity和覆盖onPause(),并onResume()与注册/注销您的接收器.只要有你所有的活动扩展BaseActivity,让他们通过打电话来super.onResume()super.onPause()往常一样.这是示例代码:

public class BaseActivity extends Activity {
    // Create an IntentFilter to listen for connectivity change events
    static IntentFilter filter = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
    // Create an instance of our BroadcastReceiver
    static ConnectivityChangedReceiver receiver = new ConnectivityChangedReceiver();

    @Override
    protected void onPause() {
        super.onPause();
        // Stop listening for connectivity change events
        unregisterReceiver(receiver);
    }

    @Override
    protected void onResume() {
        super.onResume();
        // Listen for connectivity change events
        registerReceiver(receiver, filter);
    }
}
Run Code Online (Sandbox Code Playgroud)

你的所有活动都应该扩展BaseActivity,如果他们需要做任何特别的事情,onResume()或者onPause()只是确保打电话通过super.onXXXXX()这样:

public MyActivity extends BaseActivity {
    @Override
    protected void onResume() {
        super.onResume();
        // Here you do whatever you need to do in onResume() of your activity
        ...
    }

    @Override
    protected void onPause() {
        super.onPause();
        // Here you do whatever you need to do in onPause() of your activity
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

我没有通过编译器运行代码,所以如果有错字或我错过了什么,我道歉.