Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 485b37c

Browse files
authored
iOS Background Platform Channels (#29665)
1 parent 9091526 commit 485b37c

17 files changed

+618
-123
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,8 +1157,6 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/connection_col
11571157
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/connection_collection_test.mm
11581158
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h
11591159
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.mm
1160-
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_message_router.h
1161-
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_message_router.mm
11621160
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/profiler_metrics_ios.h
11631161
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/profiler_metrics_ios.mm
11641162
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h
@@ -1190,6 +1188,9 @@ FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface_software.h
11901188
FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface_software.mm
11911189
FILE: ../../../flutter/shell/platform/darwin/ios/ios_switchable_gl_context.h
11921190
FILE: ../../../flutter/shell/platform/darwin/ios/ios_switchable_gl_context.mm
1191+
FILE: ../../../flutter/shell/platform/darwin/ios/platform_message_handler_ios.h
1192+
FILE: ../../../flutter/shell/platform/darwin/ios/platform_message_handler_ios.mm
1193+
FILE: ../../../flutter/shell/platform/darwin/ios/platform_message_handler_ios_test.mm
11931194
FILE: ../../../flutter/shell/platform/darwin/ios/platform_view_ios.h
11941195
FILE: ../../../flutter/shell/platform/darwin/ios/platform_view_ios.mm
11951196
FILE: ../../../flutter/shell/platform/darwin/ios/rendering_api_selection.h

shell/platform/darwin/common/framework/Headers/FlutterBinaryMessenger.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ typedef void (^FlutterBinaryMessageHandler)(NSData* _Nullable message, FlutterBi
3131

3232
typedef int64_t FlutterBinaryMessengerConnection;
3333

34+
@protocol FlutterTaskQueue;
35+
3436
/**
3537
* A facility for communicating with the Flutter side using asynchronous message
3638
* passing with binary messages.
@@ -44,6 +46,16 @@ typedef int64_t FlutterBinaryMessengerConnection;
4446
*/
4547
FLUTTER_DARWIN_EXPORT
4648
@protocol FlutterBinaryMessenger <NSObject>
49+
/// TODO(gaaclarke): Remove optional when macos supports Background Platform Channels.
50+
@optional
51+
- (NSObject<FlutterTaskQueue>*)makeBackgroundTaskQueue;
52+
53+
- (FlutterBinaryMessengerConnection)
54+
setMessageHandlerOnChannel:(NSString*)channel
55+
binaryMessageHandler:(FlutterBinaryMessageHandler _Nullable)handler
56+
taskQueue:(NSObject<FlutterTaskQueue>* _Nullable)taskQueue;
57+
58+
@required
4759
/**
4860
* Sends a binary message to the Flutter side on the specified channel, expecting
4961
* no reply.

shell/platform/darwin/common/framework/Headers/FlutterChannels.h

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#import "FlutterBinaryMessenger.h"
99
#import "FlutterCodecs.h"
1010

11+
@protocol FlutterTaskQueue;
12+
1113
NS_ASSUME_NONNULL_BEGIN
1214
/**
1315
* A message reply callback.
@@ -24,7 +26,8 @@ typedef void (^FlutterReply)(id _Nullable reply);
2426
* asynchronous replies back to Flutter.
2527
*
2628
* @param message The message.
27-
* @param callback A callback for submitting a reply to the sender.
29+
* @param callback A callback for submitting a reply to the sender which can be invoked from any
30+
* thread.
2831
*/
2932
typedef void (^FlutterMessageHandler)(id _Nullable message, FlutterReply callback);
3033

@@ -88,6 +91,27 @@ FLUTTER_DARWIN_EXPORT
8891
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
8992
codec:(NSObject<FlutterMessageCodec>*)codec;
9093

94+
/**
95+
* Initializes a `FlutterBasicMessageChannel` with the specified name, binary
96+
* messenger, and message codec.
97+
*
98+
* The channel name logically identifies the channel; identically named channels
99+
* interfere with each other's communication.
100+
*
101+
* The binary messenger is a facility for sending raw, binary messages to the
102+
* Flutter side. This protocol is implemented by `FlutterEngine` and `FlutterViewController`.
103+
*
104+
* @param name The channel name.
105+
* @param messenger The binary messenger.
106+
* @param codec The message codec.
107+
* @param taskQueue The FlutterTaskQueue that executes the handler (see
108+
-[FlutterBinaryMessenger makeBackgroundTaskQueue]).
109+
*/
110+
- (instancetype)initWithName:(NSString*)name
111+
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
112+
codec:(NSObject<FlutterMessageCodec>*)codec
113+
taskQueue:(NSObject<FlutterTaskQueue>* _Nullable)taskQueue;
114+
91115
/**
92116
* Sends the specified message to the Flutter side, ignoring any reply.
93117
*
@@ -142,7 +166,7 @@ typedef void (^FlutterResult)(id _Nullable result);
142166
* Invoke the callback with a `FlutterError` to indicate that the call failed.
143167
* Invoke the callback with `FlutterMethodNotImplemented` to indicate that the
144168
* method was unknown. Any other values, including `nil`, are interpreted as
145-
* successful results.
169+
* successful results. This can be invoked from any thread.
146170
*/
147171
typedef void (^FlutterMethodCallHandler)(FlutterMethodCall* call, FlutterResult result);
148172

@@ -213,6 +237,27 @@ FLUTTER_DARWIN_EXPORT
213237
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
214238
codec:(NSObject<FlutterMethodCodec>*)codec;
215239

240+
/**
241+
* Initializes a `FlutterMethodChannel` with the specified name, binary messenger,
242+
* method codec, and task queue.
243+
*
244+
* The channel name logically identifies the channel; identically named channels
245+
* interfere with each other's communication.
246+
*
247+
* The binary messenger is a facility for sending raw, binary messages to the
248+
* Flutter side. This protocol is implemented by `FlutterEngine` and `FlutterViewController`.
249+
*
250+
* @param name The channel name.
251+
* @param messenger The binary messenger.
252+
* @param codec The method codec.
253+
* @param taskQueue The FlutterTaskQueue that executes the handler (see
254+
-[FlutterBinaryMessenger makeBackgroundTaskQueue]).
255+
*/
256+
- (instancetype)initWithName:(NSString*)name
257+
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
258+
codec:(NSObject<FlutterMethodCodec>*)codec
259+
taskQueue:(NSObject<FlutterTaskQueue>* _Nullable)taskQueue;
260+
216261
// clang-format off
217262
/**
218263
* Invokes the specified Flutter method with the specified arguments, expecting
@@ -371,6 +416,27 @@ FLUTTER_DARWIN_EXPORT
371416
- (instancetype)initWithName:(NSString*)name
372417
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
373418
codec:(NSObject<FlutterMethodCodec>*)codec;
419+
420+
/**
421+
* Initializes a `FlutterEventChannel` with the specified name, binary messenger,
422+
* method codec and task queue.
423+
*
424+
* The channel name logically identifies the channel; identically named channels
425+
* interfere with each other's communication.
426+
*
427+
* The binary messenger is a facility for sending raw, binary messages to the
428+
* Flutter side. This protocol is implemented by `FlutterEngine` and `FlutterViewController`.
429+
*
430+
* @param name The channel name.
431+
* @param messenger The binary messenger.
432+
* @param codec The method codec.
433+
* @param taskQueue The FlutterTaskQueue that executes the handler (see
434+
-[FlutterBinaryMessenger makeBackgroundTaskQueue]).
435+
*/
436+
- (instancetype)initWithName:(NSString*)name
437+
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
438+
codec:(NSObject<FlutterMethodCodec>*)codec
439+
taskQueue:(NSObject<FlutterTaskQueue>* _Nullable)taskQueue;
374440
/**
375441
* Registers a handler for stream setup requests from the Flutter side.
376442
*

shell/platform/darwin/common/framework/Source/FlutterChannels.mm

Lines changed: 67 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,30 @@ static void ResizeChannelBuffer(NSObject<FlutterBinaryMessenger>* binaryMessenge
1616
[binaryMessenger sendOnChannel:FlutterChannelBuffersChannel message:message];
1717
}
1818

19+
static FlutterBinaryMessengerConnection SetMessageHandler(
20+
NSObject<FlutterBinaryMessenger>* messenger,
21+
NSString* name,
22+
FlutterBinaryMessageHandler handler,
23+
NSObject<FlutterTaskQueue>* taskQueue) {
24+
if (taskQueue) {
25+
NSCAssert([messenger respondsToSelector:@selector(setMessageHandlerOnChannel:
26+
binaryMessageHandler:taskQueue:)],
27+
@"");
28+
return [messenger setMessageHandlerOnChannel:name
29+
binaryMessageHandler:handler
30+
taskQueue:taskQueue];
31+
} else {
32+
return [messenger setMessageHandlerOnChannel:name binaryMessageHandler:handler];
33+
}
34+
}
35+
36+
////////////////////////////////////////////////////////////////////////////////
1937
@implementation FlutterBasicMessageChannel {
2038
NSObject<FlutterBinaryMessenger>* _messenger;
2139
NSString* _name;
2240
NSObject<FlutterMessageCodec>* _codec;
2341
FlutterBinaryMessengerConnection _connection;
42+
NSObject<FlutterTaskQueue>* _taskQueue;
2443
}
2544
+ (instancetype)messageChannelWithName:(NSString*)name
2645
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger {
@@ -40,18 +59,28 @@ + (instancetype)messageChannelWithName:(NSString*)name
4059
- (instancetype)initWithName:(NSString*)name
4160
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
4261
codec:(NSObject<FlutterMessageCodec>*)codec {
62+
self = [self initWithName:name binaryMessenger:messenger codec:codec taskQueue:nil];
63+
return self;
64+
}
65+
66+
- (instancetype)initWithName:(NSString*)name
67+
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
68+
codec:(NSObject<FlutterMessageCodec>*)codec
69+
taskQueue:(NSObject<FlutterTaskQueue>*)taskQueue {
4370
self = [super init];
4471
NSAssert(self, @"Super init cannot be nil");
4572
_name = [name retain];
4673
_messenger = [messenger retain];
4774
_codec = [codec retain];
75+
_taskQueue = [taskQueue retain];
4876
return self;
4977
}
5078

5179
- (void)dealloc {
5280
[_name release];
5381
[_messenger release];
5482
[_codec release];
83+
[_taskQueue release];
5584
[super dealloc];
5685
}
5786

@@ -85,7 +114,7 @@ - (void)setMessageHandler:(FlutterMessageHandler)handler {
85114
callback([codec encode:reply]);
86115
});
87116
};
88-
_connection = [_messenger setMessageHandlerOnChannel:_name binaryMessageHandler:messageHandler];
117+
_connection = SetMessageHandler(_messenger, _name, messageHandler, _taskQueue);
89118
}
90119

91120
- (void)resizeChannelBuffer:(NSInteger)newSize {
@@ -96,6 +125,7 @@ - (void)resizeChannelBuffer:(NSInteger)newSize {
96125

97126
#pragma mark - Method channel
98127

128+
////////////////////////////////////////////////////////////////////////////////
99129
@implementation FlutterError
100130
+ (instancetype)errorWithCode:(NSString*)code message:(NSString*)message details:(id)details {
101131
return [[[FlutterError alloc] initWithCode:code message:message details:details] autorelease];
@@ -136,6 +166,7 @@ - (NSUInteger)hash {
136166
}
137167
@end
138168

169+
////////////////////////////////////////////////////////////////////////////////
139170
@implementation FlutterMethodCall
140171
+ (instancetype)methodCallWithMethodName:(NSString*)method arguments:(id)arguments {
141172
return [[[FlutterMethodCall alloc] initWithMethodName:method arguments:arguments] autorelease];
@@ -175,11 +206,13 @@ - (NSUInteger)hash {
175206

176207
NSObject const* FlutterMethodNotImplemented = [[NSObject alloc] init];
177208

209+
////////////////////////////////////////////////////////////////////////////////
178210
@implementation FlutterMethodChannel {
179211
NSObject<FlutterBinaryMessenger>* _messenger;
180212
NSString* _name;
181213
NSObject<FlutterMethodCodec>* _codec;
182214
FlutterBinaryMessengerConnection _connection;
215+
NSObject<FlutterTaskQueue>* _taskQueue;
183216
}
184217

185218
+ (instancetype)methodChannelWithName:(NSString*)name
@@ -198,18 +231,27 @@ + (instancetype)methodChannelWithName:(NSString*)name
198231
- (instancetype)initWithName:(NSString*)name
199232
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
200233
codec:(NSObject<FlutterMethodCodec>*)codec {
234+
self = [self initWithName:name binaryMessenger:messenger codec:codec taskQueue:nil];
235+
return self;
236+
}
237+
- (instancetype)initWithName:(NSString*)name
238+
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
239+
codec:(NSObject<FlutterMethodCodec>*)codec
240+
taskQueue:(NSObject<FlutterTaskQueue>*)taskQueue {
201241
self = [super init];
202242
NSAssert(self, @"Super init cannot be nil");
203243
_name = [name retain];
204244
_messenger = [messenger retain];
205245
_codec = [codec retain];
246+
_taskQueue = [taskQueue retain];
206247
return self;
207248
}
208249

209250
- (void)dealloc {
210251
[_name release];
211252
[_messenger release];
212253
[_codec release];
254+
[_taskQueue release];
213255
[super dealloc];
214256
}
215257

@@ -256,7 +298,7 @@ - (void)setMethodCallHandler:(FlutterMethodCallHandler)handler {
256298
}
257299
});
258300
};
259-
_connection = [_messenger setMessageHandlerOnChannel:_name binaryMessageHandler:messageHandler];
301+
_connection = SetMessageHandler(_messenger, _name, messageHandler, _taskQueue);
260302
}
261303

262304
- (void)resizeChannelBuffer:(NSInteger)newSize {
@@ -269,10 +311,13 @@ - (void)resizeChannelBuffer:(NSInteger)newSize {
269311

270312
NSObject const* FlutterEndOfEventStream = [[NSObject alloc] init];
271313

314+
////////////////////////////////////////////////////////////////////////////////
272315
@implementation FlutterEventChannel {
273316
NSObject<FlutterBinaryMessenger>* _messenger;
274317
NSString* _name;
275318
NSObject<FlutterMethodCodec>* _codec;
319+
NSObject<FlutterTaskQueue>* _taskQueue;
320+
FlutterBinaryMessengerConnection _connection;
276321
}
277322
+ (instancetype)eventChannelWithName:(NSString*)name
278323
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger {
@@ -290,25 +335,36 @@ + (instancetype)eventChannelWithName:(NSString*)name
290335
- (instancetype)initWithName:(NSString*)name
291336
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
292337
codec:(NSObject<FlutterMethodCodec>*)codec {
338+
return [self initWithName:name binaryMessenger:messenger codec:codec taskQueue:nil];
339+
}
340+
341+
- (instancetype)initWithName:(NSString*)name
342+
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
343+
codec:(NSObject<FlutterMethodCodec>*)codec
344+
taskQueue:(NSObject<FlutterTaskQueue>* _Nullable)taskQueue {
293345
self = [super init];
294346
NSAssert(self, @"Super init cannot be nil");
295347
_name = [name retain];
296348
_messenger = [messenger retain];
297349
_codec = [codec retain];
350+
_taskQueue = [taskQueue retain];
298351
return self;
299352
}
300353

301354
- (void)dealloc {
302355
[_name release];
303356
[_codec release];
304357
[_messenger release];
358+
[_taskQueue release];
305359
[super dealloc];
306360
}
307361

308-
static void SetStreamHandlerMessageHandlerOnChannel(NSObject<FlutterStreamHandler>* handler,
309-
NSString* name,
310-
NSObject<FlutterBinaryMessenger>* messenger,
311-
NSObject<FlutterMethodCodec>* codec) {
362+
static FlutterBinaryMessengerConnection SetStreamHandlerMessageHandlerOnChannel(
363+
NSObject<FlutterStreamHandler>* handler,
364+
NSString* name,
365+
NSObject<FlutterBinaryMessenger>* messenger,
366+
NSObject<FlutterMethodCodec>* codec,
367+
NSObject<FlutterTaskQueue>* taskQueue) {
312368
__block FlutterEventSink currentSink = nil;
313369
FlutterBinaryMessageHandler messageHandler = ^(NSData* message, FlutterBinaryReply callback) {
314370
FlutterMethodCall* call = [codec decodeMethodCall:message];
@@ -354,14 +410,16 @@ static void SetStreamHandlerMessageHandlerOnChannel(NSObject<FlutterStreamHandle
354410
callback(nil);
355411
}
356412
};
357-
[messenger setMessageHandlerOnChannel:name binaryMessageHandler:messageHandler];
413+
return SetMessageHandler(messenger, name, messageHandler, taskQueue);
358414
}
359415

360416
- (void)setStreamHandler:(NSObject<FlutterStreamHandler>*)handler {
361417
if (!handler) {
362-
[_messenger setMessageHandlerOnChannel:_name binaryMessageHandler:nil];
418+
[_messenger cleanUpConnection:_connection];
419+
_connection = 0;
363420
return;
364421
}
365-
SetStreamHandlerMessageHandlerOnChannel(handler, _name, _messenger, _codec);
422+
_connection =
423+
SetStreamHandlerMessageHandlerOnChannel(handler, _name, _messenger, _codec, _taskQueue);
366424
}
367425
@end

0 commit comments

Comments
 (0)