Ant*_*tte 7 android broadcastreceiver kotlin flutter flutter-plugin
我正在构建一个需要 Radar.io SDK 某些功能的应用程序,因此我决定创建插件,以便在该项目结束后我可以与 Flutter 社区的其他成员共享该插件。问题是,我无法接收此插件中的事件。这对于插件很重要,因为为了接收地理定位触发器和其他后台事件等事件,该接收器需要接收实时信息。
我已经成功实现了https://radar.io/documentation/sdk中的 Android SDK(使用 Kotlin)中的每个功能,但是,当事件发生时,接收器不会被调用。我知道设备正在被跟踪,因为 Radar.io 仪表板中的位置已更新,但是,当发生各种事件时,接收器根本不会执行。
以下是文档告诉您如何在清单中注册接收器的方法。
<receiver
android:name=".MyRadarReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="io.radar.sdk.RECEIVED" />
</intent-filter>
</receiver>
Run Code Online (Sandbox Code Playgroud)
这适用于标准应用程序,但是,当我在清单中注册接收器时,应用程序不会在接收器所在的插件目录中查找。相反,它会查找应用程序 android 目录并返回无法找到数据路径的错误。这会导致应用程序终止。
为了解决这个问题,我发现可以通过编程方式设置接收器,所以我决定尝试一下。
在插件的主 Kotlin 文件中,我编写了以下几行以在registerWith和onAttachedToEngine. 据我了解,这些基本上是 onStart 函数。registerWith是为了与旧设备兼容而保留的旧功能。
val myRadarReceiver = MyRadarReceiver()
val intentFilter = IntentFilter()
intentFilter.addAction("io.radar.sdk.RECEIVED")
ContextWrapper(this.context).registerReceiver(myRadarReceiver, intentFilter)
Run Code Online (Sandbox Code Playgroud)
引用的类是SDK 中类MyRadarReceiver()的扩展,它扩展意味着这是我的广播接收器。这是课程:RadarReceiverBroadcastReceiver
public class MyRadarReceiver: RadarReceiver() {
override fun onEventsReceived(context: Context, events: Array<RadarEvent>, user: RadarUser) {
println("test: " + "an event was received")
}
override fun onLocationUpdated(context: Context, location: Location, user: RadarUser) {
println("test: " + "location was updated")
}
override fun onClientLocationUpdated(context: Context, location: Location, stopped: Boolean, source: Radar.RadarLocationSource) {
println("test: " + "client location updated")
}
override fun onError(context: Context, status: Radar.RadarStatus) {
println("test: " + status)
}
override fun onLog(context: Context, message: String) {
println("test: " + message)
}
}
Run Code Online (Sandbox Code Playgroud)
MyRadarReceiver当我在模拟设备上开始后台跟踪时,我期望执行其中的功能之一,但终端上没有打印任何内容。没有错误,但没有收到任何信息。这让我想知道我是否设置了错误的意图,或者接收器是否写得不正确。我不知道设置意图的另一种方法,所以我决定以更简单的形式重写 MyRadarReceiver,如下所示:
public class MyRadarReceiver: BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
println("works! Something was received")
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,控制台上没有打印任何内容,所以我现在相信它与我的意图有关。
我剩下尝试的唯一解决方案是将接收器写入应用程序而不是插件中。这可能有效,但是,我希望在完成后与 Flutter 社区分享这个插件。Radar 是一个非常强大的平台,将这个插件引入 Flutter 社区可能会产生显着的影响。
一个有用的资源是广播概述。
这取决于您是否想在运行时注册广播接收器,或者在清单中静态声明它。阅读BroadcastReceiver 的动态注册与静态注册。如果您想要启动接收器的意图,则必须静态声明它。如果您希望它仅在您的应用程序已运行时侦听,请在运行时注册它。
这都是正常的 Android 东西。
在广播接收器中,无法保证 Flutter 应用程序、Flutter Engine 或 DartVM 正在运行。如果你想运行 Flutter,你需要生成一个 Isolate。
flutterEngine = new FlutterEngine(context, null);
DartExecutor executor = flutterEngine.getDartExecutor();
backgroundMethodChannel = new MethodChannel(executor.getBinaryMessenger(), "your channel name");
backgroundMethodChannel.setMethodCallHandler(this);
// Get and launch the users app isolate manually:
executor.executeDartEntrypoint(DartExecutor.DartEntrypoint.createDefault());
Run Code Online (Sandbox Code Playgroud)
然后,您可以通过调用以下方式通知插件/ Flutter 应用程序:
// Even though lifecycle parameter is @NonNull, the implementation `FlutterEngineConnectionRegistry`
// does not use it, because it is a bug in the API design. See https://github.com/flutter/flutter/issues/90316
flutterEngine.getBroadcastReceiverControlSurface().attachToBroadcastReceiver(this, null); // This is the class you are in, the broadcast receiver
Run Code Online (Sandbox Code Playgroud)
当您即将完成广播接收器执行时:
flutterEngine.getBroadcastReceiverControlSurface().detachFromBroadcastReceiver();
Run Code Online (Sandbox Code Playgroud)
这将确保BroadcastReceiverAware在连接和分离广播接收器时通知插件。
看到 Nitrodon 的评论后,我对这个问题有了不同的看法并找到了解决方案。我不确定为什么程序化接收器初始化不起作用,但是,这是我在插件的Android 清单中放入的内容。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.youorganization.yourproject">
<application
android:name="io.flutter.app.FlutterApplication">
<receiver
android:name=".MyRadarReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="io.radar.sdk.RECEIVED" />
</intent-filter>
</receiver>
</application>
</manifest>
Run Code Online (Sandbox Code Playgroud)
您不能向应用程序标签添加 Android 标签或其他任何内容,否则会因与应用程序的 Android Manifest 冲突而引发错误。因此,您只需在仅包含名称的简单应用程序标签中声明接收者即可io.flutter.app.FlutterApplication。
| 归档时间: |
|
| 查看次数: |
14504 次 |
| 最近记录: |