从 Android 中的 BroadcastReceiver 调用 Activity 方法
Posted
技术标签:
【中文标题】从 Android 中的 BroadcastReceiver 调用 Activity 方法【英文标题】:Calling a Activity method from BroadcastReceiver in Android 【发布时间】: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)?
我可以从当前正在运行的广播接收器中获取活动(或片段)名称吗?
【问题讨论】:
【参考方案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 接口。该接口将充当BroadcastReceiver
和Activity
之间的桥梁。
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】:
使用 lambdas。 Consumer
就可以了。
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()以上是关于从 Android 中的 BroadcastReceiver 调用 Activity 方法的主要内容,如果未能解决你的问题,请参考以下文章