Java 如何从本机服务接收数据流';使用EventChannel广播接收器?
让我们假设我有一个颤振应用程序,我有一个前台服务,它有一个工作线程,并不断向我发送有关用户位置的更新,这是该服务的代码,现在返回一个随机整数: Android服务代码Java 如何从本机服务接收数据流';使用EventChannel广播接收器?,java,android,flutter,stream,Java,Android,Flutter,Stream,让我们假设我有一个颤振应用程序,我有一个前台服务,它有一个工作线程,并不断向我发送有关用户位置的更新,这是该服务的代码,现在返回一个随机整数: Android服务代码 public class LocationUpdatesService extends Service { static final int NOTIFICATION_ID = 100; static final String NOTIFICATION = "com.example.fitness_app"; Notificat
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);
}
}
}
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()}");
}
在MainActivity.java中,我接收到来自服务的广播,我应该将它们发送到颤振端:
main活动
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();
}
}
颤振省道代码
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);
}
}
}
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()}");
}
void start()异步{
试一试{
wait\u methodChannel.invokeMethod(PlatformMethods.STEPS\u COUNTER\u START);
Stream=\u eventChannel.receiveBroadcastStream();
}平台上异常捕获(e){
印刷品(
“无法运行本机服务,引发异常:${e.toString()}”);
}
这里一切正常。我可以使用Methodchannel触发服务,使用BroadcastReceiver从服务接收数据。
我需要做的就是使用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代码上也可能有多个侦听器。实际上,
BroadcastReceiver
不需要作为sink.success(步骤)
可以由绑定的本地服务代码直接调用谢谢Richard,它非常有用,我可以获取流。但是我需要我的服务继续工作,即使颤振活动被终止。那么,你建议如何处理列表广播接收器,我必须在destroy上注销它们吗?还有一个问题:如果地面服务正在运行,FlatterActivity被终止,如何保持服务的价值,以便应用程序可以从停止的位置继续运行?我正在考虑使用SharedReferences。那么你怎么看?@pskink实际上,当FlatterActivity被终止时,我需要服务继续工作,这样我就不能将其绑定到活动。@SameerAhmad,是的您可以-服务可以启动和绑定,更多