1.背景
由于项目需要,需要对接别的app的广播,就看了看Net 安卓开发的广播接收,看官网的介绍单纯广播和接收都挺简单的,于是上手样板项目弄了两个demo出来,app1用来发,app2用来收。
2.版本
:使用都是最新版对应安卓14,api34。
3.app1广播
广播为了方便测试,加了一个输入框和按钮,方便点击按钮发送广播查看效果。
app1广播代码:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp"
android:gravity="center_horizontal">
<EditText
android:id="@+id/inputText"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:hint="请输入"
android:inputType="text"
android:layout_marginBottom="16dp" />
<Button
android:id="@+id/buttonSubmit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="提交"
android:background="?android:attr/textColorPrimaryInverse"
android:textColor="@android:color/black"
android:layout_gravity="center_horizontal"
android:padding="10dp" />
</LinearLayout>
MainActivity
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
// 获取布局中的控件
EditText inputText = FindViewById<EditText>(Resource.Id.inputText);
Button buttonSubmit = FindViewById<Button>(Resource.Id.buttonSubmit);
// 为按钮设置点击事件监听器
buttonSubmit.Click += (sender, e) => {
// 获取输入框中的文本
string text = inputText.Text;
// 在这里处理文本,例如显示一个Toast或者发送数据到服务器等
Toast.MakeText(this, "广播: " + text, ToastLength.Short).Show();
BroadcastMessage(text);
};
}
private void BroadcastMessage(string value)
{
// 创建一个新的Intent对象
Intent intent = new Intent("test");
//intent.SetPackage("com.companyname.AndroidApp2");
//intent.SetComponent(new ComponentName("com.companyname.AndroidApp2", ".Receiver"));
// 如果你想传递额外的数据,可以添加到Intent的Extras中
intent.PutExtra("key", value);
// 发送广播
SendBroadcast(intent);//, "com.companyname.permissions.my_broadcast"
}
为了尝试这个广播接收淌了很多坑,像intent.SetPackage和intent.SetComponent发送的时候都不是必须指定的(新旧版本都不需要),唯一需要指定的就是new Intent(“test”)中的这个action。
到这里发送广播就完事了。
4.app2接收
MyReceiver
[BroadcastReceiver(Enabled = true, Exported = true)]
//[IntentFilter(new[] { "com.companyname.AndroidApp2.ReceiverFilter" })]
public class MyReceiver : BroadcastReceiver
{
public override void OnReceive(Context? context, Intent? intent)
{
if (intent != null)
{
Log.Info("接收", intent.Action);
var value = intent.GetStringExtra("key");
Log.Info("接收", value.ToString());
}
}
}
MainActivity 中动态注册
private MyReceiver _receiver;
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
_receiver = new MyReceiver();
}
protected override void OnResume()
{
base.OnResume();
RegisterReceiver(_receiver, new IntentFilter("test"));
}
代码跟官网的没什么差别。
官网链接
但是问题就出现在用api34这里,运行后就直接报错提示Receive_Exported或者Receive_Not_Exported错误。
在 Android 应用中,广播接收器可以设置为“导出”(exported)或“非导出”(not exported)。导出意味着其他应用可以发送广播到这个接收器;非导出则意味着只有同一应用内部的组件可以发送广播到这个接收器。
看到这里我想的事难道Net版本的不同app之间不支持动态注册了吗(RegisterReceiver函数不像java中一样有参数可以控制exported),官网也没有通知。
于是改为静态注册,仍然失败:
AndroidManifest.xml
<application android:allowBackup="true"
android:icon="@mipmap/appicon"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@android:style/Theme.Material.Light.DarkActionBar">
<receiver android:name=".MyReceiver" android:exported="true" android:enabled="true" >
--><!--android:permission="com.companyname.permissions.my_broadcast"-->
<intent-filter>
<action android:name="test"/>
</intent-filter>
</receiver>
</application>
之后翻看各种博文,浪费了一天多的时间,最后无奈之下打算用xamarin创建然后再升级(2024.5.1后不再支持xamarin,一条相当费劲的路)。
这里是解决这个问题的一个引子,创建的xamarin安卓应用要执行的时候发现Android SDK 支持不到34,最高只有33,
这里只建了一个接收,因为发送没有什么问题。
建立完后,执行,不错接收到了。
期间还尝试了Maui来建立,同样是失败的。
突然想到了33版本
就想着再试一下,不然真要费劲去升级了。
设置项目的AndroidManifest.xml文件里的uses-sdk的targetSdkVersion
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33" />
这里设置为了33,执行,没有报错,至少启动成功了。
然后开始广播,等待了一会接收到了,不用考虑升级了。