我在将数据从
BroadcastReceiver
传递到 Activity
时遇到严重问题。仔细看看我的问题。我有一个类PhoneStateReceiver extends BroadcastReceiver
用来接收来电。
public class PhoneStateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
try {
System.out.println("Receiver start");
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
if(state.equals(TelephonyManager.EXTRA_STATE_RINGING)){
}
}
catch (Exception e){
e.printStackTrace();
}
}
}
来电将发送至
Activity
,称为ReceiverActivity
。 ReceiverActivity
接收来电并通过套接字连接将其发送到服务器。套接字连接在 onCreate
函数中初始化。我用谷歌搜索并找到了将数据从 BroadcastReceiver
传递到 Activity
的服务器方式。常见的方式是通过putExtra
函数发送数据并调用startActivity
。但是,该方法会再次调用onCreate
,然后连接套接字,重新绘制UI。因此,这对我的情况没有帮助。
在我的目标中,如果手机收到来电,它会将来电发送到
ReceiverActivity
。 ReceiverActivity
接收消息并调用发送函数。哪种方法最好?谢谢你
将数据从
BroadcastReceiver
传递到 ReceiverActivity
的常用方法如下
在 PhoneStateReceiver 类中:
Intent intent_phonenum = new Intent(context, ReceiverActivity.class);
intent_phonenum.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent_phonenum.putExtra("phone_num", incomingNumber);
context.startActivity(intent_phonenum);
在 ReceiverActivity 类中:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
connect_socket();
Intent intent = getIntent();
phone_num = intent.getStringExtra("phone_num");
send(phone_num);
}
简单,无需任何第三方库。
确保
BroadcastReceiver
必须在 OnPause()
上注册并取消注册。
你必须做两件事
在您的活动中注册接收者,如下所示。
public class MainActivity extends Activity {
Context context;
BroadcastReceiver updateUIReciver;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = this;
IntentFilter filter = new IntentFilter();
filter.addAction("service.to.activity.transfer");
updateUIReciver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//UI update here
if (intent != null)
Toast.makeText(context, intent.getStringExtra("number").toString(), Toast.LENGTH_LONG).show();
}
};
registerReceiver(updateUIReciver, filter);
}
}
现在为您服务
public class PhoneStateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
try {
System.out.println("Receiver start");
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
Intent local = new Intent();
local.setAction("service.to.activity.transfer");
local.putExtra("number", incomingNumber);
context.sendBroadcast(local);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
您可以在此处使用一个非常简单的设计模式来简化类之间的通信并解耦代码:
publisher/subscriber
。我最喜欢的图书馆是EventBus
:
首先,添加到您的 build.gradle 文件:
compile 'org.greenrobot:eventbus:3.0.0'
然后,创建一个简单的
POJO - Plain Old Java Object
,如下所示:
public class OnReceiverEvent{
private String phoneNumber;
public OnReceiverEvent(String phone){
this.phoneNumber = phone;
}
public String getPhoneNumber(){
return phoneNumber;
}
}
接下来,通过将您的
Receiver
类设为 publisher
,并将您的 Activity
设为 subscriber
,您应该能够轻松地将信息传递到您的活动,如下所示:
//inside your PhoneStateReceiver class when you want to pass info
EventBus.getDefault().post(new OnReceiverEvent(phoneNumber));
接下来,在您的活动中,只需执行以下操作:
//onStart
@Override
public void onStart(){
super.onStart();
EventBus.getDefault().register(this);
}
//onStop
@Override
public void onStop(){
super.onStop();
EventBus.getDefault().unregister(this);
}
最后,处理发布的数据,即电话号码值:
@Subscribe
public void onPhoneNumberReceived(OnReceiverEvent event){
//get the phone number value here and do something with it
String phoneNumber = event.getPhoneNumber();
//display or something?
}
更新
如果您希望此活动订阅另一个 Event,只需使用
@Subscribe
注释创建一个方法,就像在第一个方法中所做的那样。
@Subscribe
public void onSomeOtherEvent(EventClassName event){
//get the variables here as usual;
}
这是将数据从接收器传递到您的活动的最简单方法,而不必担心一遍又一遍地启动活动!
我希望这有帮助,祝你好运!
所以我理解您不想每次都重新创建您的活动。
在您的
Intent
中更改此标志将对您有所帮助:
intent_phonenum.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
在 Intent 类中,如果您阅读了
FLAG_ACTIVITY_CLEAR_TOP
的方法摘要:
- 如果设置,并且正在启动的活动已在
中运行- 当前任务,而不是启动该活动的新实例,
- 其上的所有其他活动都将被关闭,并且此意图
- 将作为新 Intent 传递到(现在位于顶部)旧活动。 (您可以阅读更多...)
在这种情况下:如果您的应用程序正在运行并且您有一个 Activity 实例,那么
Intent
将不会重新创建您的 Activity。但假设您的应用程序处于关闭状态,并且当 BroadcastReceiver 触发时,Intent
将创建新的 Activity,因为您没有该 Activity 的实例。
@编辑:
您可以在
BroadcastReceiver
中指定特殊意图:
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
Intent i = new Intent("mycustombroadcast");
i.putExtra("phone_num", incomingNumber);
context.sendBroadcast(i);
}
然后在你的Activity里面
onCreate()
这样注册接收者:
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
int incoming_number= bundle.getInt("phone_num");
Log.e("incoming number", "" + incoming_number);
}
};
//then register receiver like that :
registerReceiver(broadcastReceiver, new IntentFilter("mycustombroadcast"));
您可以在
onDestroy()
中注销接收器:unregisterReceiver(broadcastReceiver);
另一种方法是在您的 Activity 中覆盖
onNewIntent()
:
@Override
protected void onNewIntent(Intent intent) {
//your intent is here, you can do sth.
super.onNewIntent(intent);
}
这对我有用。
广播接收器
class SMSReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == Telephony.Sms.Intents.SMS_RECEIVED_ACTION) {
val messages = Telephony.Sms.Intents.getMessagesFromIntent(intent)
for (message in messages) {
val ourIntent = Intent(intent.action).apply { putExtra("message", message.messageBody) }
LocalBroadcastManager.getInstance(context).sendBroadcast(ourIntent)
}
}
}
}
活动
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val message = intent.getStringExtra("message").toString()
println("__print.MainActivity.onReceive::message::$message")
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val filter = IntentFilter().apply { addAction(Telephony.Sms.Intents.SMS_RECEIVED_ACTION) }
LocalBroadcastManager.getInstance(this).registerReceiver(receiver, filter)
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(receiver)
}
}