【问题标题】:Calling a Activity method from BroadcastReceiver in Android从 Android 中的 BroadcastReceiver 调用 Activity 方法
【发布时间】:2014-04-10 02:31:43
【问题描述】:

这里我正在创建一个仅依赖于 Internet 的在线应用程序。

因此,每当出现网络错误时,它都必须通知用户。为此,我创建了一个 BroadcastReciver,它在网络连接丢失(Internet)时接收呼叫。

这一切都完美无缺。现在我需要的是我必须从这个广播接收器调用一个 Activity 方法,我在其中创建了一个警报对话。

我在 stack-overflow.com 上阅读了很多答案,我可以将该方法声明为静态并仅使用 Activity 名称进行调用,

例如MyActivityName.myMethod()

但我不能将我的方法声明为静态,因为我在那里使用警报对话,它在线显示错误,

AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);

不能在静态上下文中使用它

那么,我怎样才能从广播接收器调用 Activity 的方法(不能是静态的且不启动该 Activity)?

我可以从当前正在运行的广播接收器中获取活动(或片段)名称吗?

【问题讨论】:

    标签: android methods android-activity broadcastreceiver static-methods


    【解决方案1】:

    试试这个代码:

    您的网络丢失类的广播接收器类:

    public class InternetLostReceiver extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
        context.sendBroadcast(new Intent("INTERNET_LOST"));
    }
    }
    

    在你的活动中添加这个来调用广播:

    public class TestActivity  extends Activity{
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        registerReceiver(broadcastReceiver, new IntentFilter("INTERNET_LOST"));
    }
    
    BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            // internet lost alert dialog method call from here...
        }
    };
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(broadcastReceiver);
    }
    }
    

    【讨论】:

    • 感谢您的代码 jay,它运行良好。我在 onReceive() 中添加了用于创建警报对话的代码。只有一个错误存在。每当互联网断开连接时,都会立即创建四个警报对话,而不是一个。
    • 如果打开AlertDialog,请输入if条件,如果打开而不打开另一个。请,如果它的工作比接受我的回答。
    • AlertDialog.Builder alertDialog = new AlertDialog.Builder(this); alertDialog.setMessage("找不到网络。"); alertDialog.setPositiveButton("检查设置", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { } }); alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { } }); alertDialog.show();
    • 附注:内部BroadcastReceiver 不得与外部BroadcastReceiver 具有相同的意图过滤器。如果他们这样做,您将获得无限循环。
    • 谢谢你节省了我的时间:)
    【解决方案2】:

    接口:将广播接收器和活动代码分开!

    您可以创建一个 CallBackListener 接口。该接口将充当BroadcastReceiverActivity 之间的桥梁。

    1) 创建回调监听器

    interface ConnectionLostCallback{
    
          public void connectionLost();
    
    } 
    

    2) 在您的 BroadcastReceiver 中提供ConnectionLostCallback

    public class MyBroadcastReceiver extends BroadcastReceiver{
    
         private ConnectionLostCallback listener;
    
         public MyBroadcastReceiver(ConnectionLostCallback listener ){
    
               this.listener = listener     //<-- Initialze it
    
         }
    
         @Override
         public void onReceive(Context context, Intent intent) {
    
               listener.connectionLost();
    
         }
    }
    

    3) 在您的 Activity 中实现 ConnectionLostCallback 并覆盖该方法

    YourActvity extends AppcompatActivity implements ConnectionLostCallback{
    
        // Your Activity related code //
          //    new MyBroadcastReceiver(this);  <-- create instance
    
        private void showAlertMessage(){
           AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
        } 
    
    
        @Override 
        public void connectionLost(){
    
             showAlertMessage();          //<--- Call the method to shoe alert dialog
    
        }
    
    
    }
    

    相关链接:

    如果您想知道如何使 BroadcastReceiver 独立于任何 活动即你如何重用相同的广播接收器 不同的活动?然后READ THIS

    【讨论】:

    • 如果不能调用构造函数怎么办?例如,使用AlarmManager时,从alarmmanager方法调用广播接收器
    • 如果您想跟踪 wifi 状态变化,情况相同 - 那是在清单级别并且您捕获系统级别的广播。在这种情况下,设置一个监听器
    【解决方案3】:

    在您打开警报对话框的活动中添加一个布尔变量

    boolean isDialogOpened = false;
    
    // in broadcast recever check 
    if(isDialogOpened) {
        alertDialog();
    }
    

    并用这个替换你的 alertdialog 代码

    public void alertDialog() {
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
    
        alertDialog.setMessage("Network not found.");
        alertDialog.setPositiveButton("Check Setting",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                    }
                });
        alertDialog.setNegativeButton("Cancel",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                    }
                });
    
        alertDialog.setOnDismissListener(new OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialog) {
                isDialogOpened = false;
            }
        });
    
        alertDialog.setOnCancelListener(new OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialog) {
                isDialogOpened = false;
            }
        });
    
        alertDialog.show();
    }
    

    【讨论】:

    • 抱歉,您的代码不起作用,在 alertDialog.setonDismissListenet 上告诉我“NoSuchMethodException”
    【解决方案4】:

    将 Activity 的上下文传递给 BroadcastReceiver 的构造函数。

    public class ResponseReceiver extends BroadcastReceiver{
    
        MainActivity ma; //a reference to activity's context
    
        public ResponseReceiver(MainActivity maContext){
            ma=maContext;
        }
    
        @Override
        public void onReceive(Context context, Intent intent) {
            ma.brCallback("your string"); //calling activity method
        }
    
    }
    

    在你的 MainActivity 中

    public class MainActivity extends AppCompatActivity {
        ...
        public void onStart(){
            ...        
        ResponseReceiver responseReceiver = new ResponseReceiver(this); //passing context
        LocalBroadcastManager.getInstance(this).registerReceiver(responseReceiver,null);
            ...
        }
    
        public void brCallback(String param){
            Log.d("BroadcastReceiver",param);
        }
    }
    

    希望对你有帮助

    【讨论】:

    • 你试过了吗?我认为这不起作用,因为brCallback 不是AppCompatActivity 的有效消息。当然,你可以降低你的活动,但你最终会耦合。
    【解决方案5】:

    使用 lambdasConsumer 就可以了。

    protected void onCreate(Bundle savedInstanceState) {
        ...
    
        receiver = new LocationBroadcastReceiver((whatever) -> doSomething(whatever));
        registerReceiver(receiver, new IntentFilter("YOUR_MESSAGE"));
    }
    

    doSomething 将是您的 Activity 中的一个方法。

    ...

    class YourBroadcastReceiver extends BroadcastReceiver {
    
        private Consumer<Whatever> callback;
    
        public LocationBroadcastReceiver(Consumer<Whatever> callback) {
            this.callback = callback;
        }
    
        @RequiresApi(api = Build.VERSION_CODES.N)
        @Override
        public void onReceive(Context context, Intent intent) {
                
            this.callback.accept(new Whatever());
        }
    }
    

    是所有其他的替代品:

    将该方法声明为静态并仅使用 Activity 名称进行调用。

    除了你解释的,这是一种耦合方式。

    将 Activity 的上下文传递给 BroadcastReceiver 的构造函数。

    这行不通,因为您想调用不属于AppCompatActivity 的方法。是的,你可能会沮丧,但你最终会与你的活动耦合。

    改用另一个广播或本地广播

    嗯,你只能通过这种方式传递一堆原语。如果你想传递一个对象怎么办?此外,声明一个新的 BroadcastReceiver 会变得非常冗长,而且可能难以理解。

    【讨论】:

      【解决方案6】:

      与 Vijju 的回答相同,但改用本地广播

      public class SampleReceiver extends BroadcastReceiver {
      
          @Override
          public void onReceive(Context context, Intent intent) {
              Intent intentToBroadcast =  new Intent("YOUR_ACTION_HERE");
              LocalBroadcastManager.getInstance(context).sendBroadcast(intentToBroadcast);
          }
      }
      

      在你的活动中添加这个

      public class SampleActivity extends Activity {
      
          @Override
          protected void onResume() {
              super.onResume();
              LocalBroadcastManager.getInstance(this).registerReceiver(mSampleReceiver, new IntentFilter(YOUR_ACTION_HERE));
          }
      
          @Override
          protected void onPause() {
              LocalBroadcastManager.getInstance(this).unregisterReceiver(mSampleReceiver);
              super.onPause();
          }
      
          private SampleReceiver mSampleReceiver = new BroadcastReceiver() {
              @Override
              public void onReceive(Context context, Intent intent) {
                  // your code here
              }
          };
      }
      

      注意将注册/取消注册调用移动到 onCreate/onDestroy 是您希望即使您的活动在后台也能收到通知。

      【讨论】:

      • 当我想像你一样声明一个变量时:“private SampleReceiver mSampleReceiver = new BroadcastReceiver()”,给我错误,要求类型:SampleReceiver,但提供的是 BroadcastReceiver
      • 尝试用新的 SampleReceiver() 替换新的 BroadcastReceiver()
      猜你喜欢
      • 1970-01-01
      • 2011-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-06
      • 1970-01-01
      • 2011-06-01
      相关资源
      最近更新 更多