Xamarin.Android短信接收事件无法传递至Xamarin.Forms的问题求助
解决Xamarin.Android短信接收器事件在Forms中无法触发的问题
我之前也踩过这个坑!你遇到的Received事件始终为null的核心原因是:Android系统在收到短信时会自动实例化一个新的IncomingSms对象来处理广播,而你通过DependencyService.Get<IReceived>()获取的是另一个完全独立的实例。这两个实例的事件是各自独立的,系统触发的那个实例根本没有订阅者,自然Received就是null了。
下面给你两种靠谱的解决方法,推荐第一种,更符合Xamarin.Forms的跨平台设计:
方法一:使用Xamarin.Forms自带的MessagingCenter(推荐)
MessagingCenter是Xamarin官方提供的跨平台消息传递机制,不需要依赖实例,直接在Android端发送消息,Forms端订阅即可,完美避开实例不匹配的问题。
步骤1:修改Android端的短信接收器
把原来触发Received事件的代码,换成发送MessagingCenter消息:
private void OnMessagesReiceved(SmsMessage[] messages) { var XMessages = new List<XxmsApp.Model.Message>(); for (var i = 0; i < messages.Length; i++) { XMessages.Add(new XxmsApp.Model.Message { Address = messages[i].OriginatingAddress, Value = messages[i].MessageBody }); } // 发送短信接收消息,"SmsReceived"是自定义的消息标识,要和订阅端一致 MessagingCenter.Send<object, List<XxmsApp.Model.Message>>(this, "SmsReceived", XMessages); }
步骤2:在Forms端订阅消息
修改你的App类,去掉原来的DependencyService事件订阅,换成MessagingCenter订阅:
public App() { DBUpdates(); MainPage = new MasterDetailPage() { Master = new MenuPage { Title = "Title" }, Detail = new NavigationPage(new XxmsApp.MainPage()) { BarBackgroundColor = Color.Black } }; // 订阅短信接收消息 MessagingCenter.Subscribe<object, List<XxmsApp.Model.Message>>( this, "SmsReceived", (sender, messages) => { // 调用原来的处理逻辑 XMessages_Received(messages); }); } private void XMessages_Received(IEnumerable<Model.Message> message) { // 你的短信处理代码 }
方法二:使用静态事件(备选)
如果不想用MessagingCenter,可以把事件改成静态的,这样所有实例共享同一个事件订阅:
步骤1:修改Android端的IncomingSms类
把实例事件改成静态事件:
public class IncomingSms : BroadcastReceiver, IReceived { // 把事件改成静态的 public static event OnReceived Received; public override void OnReceive(Context context, Intent intent) { if (intent.Action != Telephony.Sms.Intents.SmsReceivedAction) return; SmsMessage[] messages = Telephony.Sms.Intents.GetMessagesFromIntent(intent); OnMessagesReiceved(messages); } private void OnMessagesReiceved(SmsMessage[] messages) { var XMessages = new List<XxmsApp.Model.Message>(); for (var i = 0; i < messages.Length; i++) { XMessages.Add(new XxmsApp.Model.Message { Address = messages[i].OriginatingAddress, Value = messages[i].MessageBody }); } // 触发静态事件 Received?.Invoke(XMessages); } }
步骤2:在Forms端订阅静态事件
直接订阅静态事件,不需要通过DependencyService:
public App() { DBUpdates(); MainPage = new MasterDetailPage() { Master = new MenuPage { Title = "Title" }, Detail = new NavigationPage(new XxmsApp.MainPage()) { BarBackgroundColor = Color.Black } }; // 订阅静态事件 XxmsApp.Api.IncomingSms.Received += XMessages_Received; }
⚠️ 注意:静态事件容易导致内存泄漏,记得在App退出时取消订阅:
protected override void OnSleep() { XxmsApp.Api.IncomingSms.Received -= XMessages_Received; } protected override void OnResume() { XxmsApp.Api.IncomingSms.Received += XMessages_Received; }
额外需要检查的配置
除了上面的代码修改,还要确保以下配置正确,不然接收器可能根本不触发:
- 添加权限:在Android项目的
AndroidManifest.xml里添加短信相关权限:
<uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.READ_SMS" />
- 动态申请权限:Android 6.0(API 23)及以上,
RECEIVE_SMS是危险权限,需要在运行时申请。可以在Forms启动时或者Android项目的MainActivity里申请:
// 在MainActivity的OnCreate方法中 if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.ReceiveSms) != Permission.Granted) { ActivityCompat.RequestPermissions(this, new string[] { Manifest.Permission.ReceiveSms }, 100); }
- BroadcastReceiver属性配置:确保你的
BroadcastReceiver属性里的Exported设置为true(Android 12及以上要求接收系统广播的接收器必须显式设置Exported):
[BroadcastReceiver(Enabled = true, Label = "SMS Receiver", Exported = true)] [IntentFilter(new string[] { Telephony.Sms.Intents.SmsReceivedAction })] public class IncomingSms : BroadcastReceiver, IReceived { // ... }
按照上面的步骤修改后,应该就能正常在Forms中接收到短信事件了!
内容的提问来源于stack exchange,提问作者Александр
相关产品推荐
相关产品推荐

