java - 如何使用 EventChannel 从本机服务的 BroadcastReciever 接收数据流?
问题描述
假设我有一个颤振应用程序,我有一个前台服务,它有一个工作线程并不断向我发送有关用户位置的更新,这是服务的代码,它现在返回一个随机整数:
安卓服务代码
public class LocationUpdatesService extends Service {
static final int NOTIFICATION_ID = 100;
static final String NOTIFICATION = "com.example.fitness_app";
NotificationManagerCompat m_notificationManager;
private Intent m_broadcastInent;
private final String TAG = this.getClass().getSimpleName();
private AtomicBoolean working = new AtomicBoolean(true);
private int steps = 0;
private Runnable runnable = new Runnable() {
@Override
public void run() {
while(working.get()) {
steps++;
m_notificationManager.notify(NOTIFICATION_ID,
createNotification("Steps Counter" + steps ,
R.drawable.common_full_open_on_phone, 1));
m_broadcastInent.putExtra("steps", steps);
sendBroadcast(m_broadcastInent);
}
}
};
@Override
public void onCreate() {
m_broadcastInent = new Intent(NOTIFICATION);
m_notificationManager = NotificationManagerCompat.from(this);
createNotificationChannel();
startForeground(NOTIFICATION_ID, createNotification("Steps Counter" ,
R.drawable.common_full_open_on_phone, 0));
super.onCreate();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(runnable).start();
return Service.START_STICKY;
}
@Override
public void onDestroy() {
working.set(false);
m_notificationManager.cancel(NOTIFICATION_ID);
super.onDestroy();
}
private Notification createNotification(String title, int icon, int steps) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this,
getString(R.string.BACKGROUND_SERVICE_NOTIFICATION_CHANNEL_ID));
builder.setNumber(steps);
builder.setSmallIcon(icon);
builder.setContentTitle(title);
builder.setOnlyAlertOnce(true);
return builder.build();
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = getString(R.string.BACKGROUND_SERVICE_NOTIFICATION_CHANNEL_ID);
String description =
getString(R.string.BACKGROUND_SERVICE_NOTIFICATION_CHANNEL_DESCRIPTION);
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel =
new NotificationChannel(getString(
R.string.BACKGROUND_SERVICE_NOTIFICATION_CHANNEL_ID), name, importance);
channel.setDescription(description);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
}
在 MainActivity.java 我正在接收来自服务的广播,我应该将它们发送到颤振端:
主要活动
public class MainActivity extends FlutterActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private static final String ONE_TIME_BACKGROUND_METHOD_CHANNEL = "fitness_app/method_one_time_service";
private static final String EVENTS_STREAM_CHANNEL = "fitness_app/event_one_time_service";
private Intent m_serviceIntent;
private MethodChannel m_methodChannel;
private EventChannel m_eventchannel;
private EventChannel.EventSink m_stepsStreamSink;
private EventChannel.StreamHandler m_eventCallHandler;
private MethodChannel.Result m_result;
private EventChannel.EventSink m_eventSink;
private BroadcastReceiver m_serviceBroadcastReciever = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Log.d(TAG, "milliseconds " + intent.getIntExtra("steps", 0));
Bundle bundle = intent.getExtras();
if (bundle != null) {
int steps = bundle.getInt("steps");
/////////////////////////////////////////
/////////////////////////////////////////
// I need Here To add Data To the stream
/////////////////////////////////////////
/////////////////////////////////////////
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
m_serviceIntent = new Intent(this, LocationUpdatesService.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, m_serviceIntent, 0);
m_methodChannel = new MethodChannel(getFlutterView(), ONE_TIME_BACKGROUND_METHOD_CHANNEL);
m_methodChannel.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
if (methodCall.method.equals("START_STEPS_COUNTER")) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(m_serviceIntent);
} else {
startService(m_serviceIntent);
}
} else {
stopService(m_serviceIntent);
}
}
});
m_eventchannel = new EventChannel(getFlutterView(), EVENTS_STREAM_CHANNEL);
m_eventCallHandler = new EventChannel.StreamHandler() {
@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
m_eventSink = eventSink;
}
@Override
public void onCancel(Object o) {
}
};
m_eventchannel.setStreamHandler(m_eventCallHandler);
}
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onResume() {
super.onResume();
registerReceiver(m_serviceBroadcastReciever, new IntentFilter(LocationUpdatesService.NOTIFICATION));
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
颤振飞镖代码
void start() async {
try {
await _methodChannel.invokeMethod(PlatformMethods.STEPS_COUNTER_START);
Stream<int> stream = _eventChannel.receiveBroadcastStream();
} on PlatformException catch (e) {
print(
" Faild to run native service with thrown exception : ${e.toString()}");
}
这里的一切都很好。我可以使用Methodchannel触发服务,我使用 BroadCastREciever 从服务接收数据。我需要做的就是使用 EventChannel 从本机代码返回一个流。
解决方案
创建一个扩展 BroadcastReceiver 的类并传递一个 EventChannel.EventSink。
class SinkBroadcastReceiver(private val sink: EventChannel.EventSink) {
override fun onReceive(context: Context, intent: Intent) {
val bundle = intent.getExtras()
if (bundle != null) {
val steps = bundle.getInt("steps")
sink.success(steps)
}
}
}
然后,改为在声明中创建 BroadcastReceiver,您可以在 onListen 中创建它并在那里调用 registerReceiver:
m_eventCallHandler = new EventChannel.StreamHandler() {
@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
SinkBroadcastReceiver receiver = new SinkBroadcastReceiver(eventSink);
registerReceiver(receiver, new IntentFilter(LocationUpdatesService.NOTIFICATION));
// TODO : Save receiver in a list to call unregisterReceiver later
}
@Override
public void onCancel(Object o) {
}
};
您可能需要跟踪列表中的所有接收者,因为您可能需要在活动停止时取消注册。此外,当您停止服务时,您可能需要遍历已注册 BroadcastReceiver 的列表以取消注册所有实例。
这样,您也可以在同一事件的 dart 代码上拥有多个侦听器。
推荐阅读
- python - 关于使用 jupyter notebook 的 python 中的关键错误
- extjs - Extjs Panel 渲染两次?
- jquery - 未从控制器中的 ajax 调用获取数据----所需的数据参数“数据”不存在
- python - Python av在无限循环中播放文件
- java - 仅当前一个抛出异常时才执行可完成的期货列表
- java - Spring boot JPQL 对位运算符的支持
- python - 再现全连接顺序层
- python - 从一个运行多个 shell 脚本并在每次完成时执行一些操作
- android - 在 Viewport Android App 上从 Wordpress OneSignal 插件发送通知
- javascript - 如何选择具有此 ID 的类来触发事件/如何更改每张幻灯片的标题颜色?