首页 > 解决方案 > 如何使用 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 从本机代码返回一个流。

标签: javaandroidflutterstream

解决方案


创建一个扩展 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 代码上拥有多个侦听器。


推荐阅读