Line data Source code
1 : part of './services.nativechannels.dart';
2 :
3 : /// An implementation of [IPlatformEntrypoint] that uses method channels.
4 : class PlatformEntrypoint extends IPlatformEntrypoint {
5 : static const String _tag = 'PlatformEntrypoint';
6 :
7 2 : PlatformEntrypoint({
8 : required String id,
9 : required String mainChannelId,
10 : required MethodChannel methodChannel,
11 : required EventChannel eventChannel,
12 : required CallBacksController callBacksController,
13 2 : }) : super(
14 : id: id,
15 : mainChannelId: mainChannelId,
16 : methodChannel: methodChannel,
17 : eventChannel: eventChannel,
18 : callbacksController: callBacksController);
19 :
20 : static const String setupMethodHandler = 'callback';
21 :
22 : static const String platformCallBackMethodHandler = 'platformCallBackMethodHandler';
23 :
24 : /// Remember that proto3 doesn't allow [required] fields anymore.
25 : /// AND, [Message] was generated by our .proto config file.
26 : /// Because of this I put this 'factory' here as an extension.
27 2 : static Message defaultListenerSetup({
28 : required namespace,
29 : required targetMethod,
30 : required targetMethodCancellation,
31 : Result? args,
32 : }) {
33 2 : return Message(
34 2 : header: Header(
35 : id: '_',
36 : namespace: namespace,
37 : targetMethod: targetMethod,
38 : targetMethodCancellation: targetMethodCancellation,
39 : platformCallBackMethodHandler: PlatformEntrypoint.platformCallBackMethodHandler,
40 : intent: Header_CommunicationType.SETUP,
41 2 : lastUpdated: Timestamp.fromDateTime(
42 2 : DateTime.now(),
43 : ),
44 : ),
45 2 : payload: Payload(
46 : result: args,
47 : ),
48 : );
49 : }
50 :
51 : @override
52 1 : Future<CancelListening> startListening({
53 : required Message message,
54 : required MultiUseCallback<MirrorMethodCall, Error> callback,
55 : }) async {
56 3 : await callbacksController.disposeActiveCallbackListener(
57 2 : targetMethod: message.header.targetMethod,
58 1 : listenerCancelation: listenerCancelation,
59 : );
60 :
61 1 : final callbackMethod = CallBackMethod<MirrorMethodCall, Error>(
62 : message: message,
63 : call: callback,
64 : );
65 :
66 2 : callbacksController.setCallBack(call: callbackMethod);
67 :
68 1 : methodChannel
69 3 : .setMethodCallHandler(callbacksController.platformCallBackMethodHandlerSetup);
70 :
71 3 : message.header.id = id;
72 :
73 4 : message.header.callBackReferenceId = callbacksController.lastAddedcallBackReferenceId;
74 :
75 3 : final _ = await methodChannel.invokeMethod(
76 : PlatformEntrypoint.setupMethodHandler,
77 1 : message.writeToBuffer(),
78 : );
79 :
80 1 : return listenerCancelation(message);
81 : }
82 :
83 1 : CancelListening listenerCancelation(Message message) {
84 : // send same message to the [listener cancellation]
85 2 : message.header.intent = Header_CommunicationType.CANCELATION;
86 :
87 1 : return () async {
88 : try {
89 3 : final response = await methodChannel.invokeMethod(
90 : PlatformEntrypoint.setupMethodHandler,
91 1 : message.writeToBuffer(),
92 : );
93 :
94 : /// TODO(v): catch only with unit tests mock
95 : if (response == null) {
96 : return;
97 : }
98 :
99 0 : log('entrypoint -> listenerCancelation\n${message.header.targetMethodCancellation}\n');
100 : } catch (e, s) {
101 0 : log('listenerCancelation -> CancelListening\n',
102 : name: _tag, stackTrace: s, error: e);
103 : rethrow;
104 : }
105 : };
106 : }
107 :
108 1 : @override
109 1 : Stream<EventMessage> get eventMessageStream => eventChannel
110 1 : .receiveBroadcastStream()
111 1 : .cast<Map<dynamic, dynamic>>()
112 2 : .map((map) {
113 1 : return EventMessage.fromMap(map);
114 : });
115 :
116 : /// throws:
117 : /// [ChannelInvalidAnswerException]
118 : /// [Exception]
119 : @override
120 1 : Future<Message> send(Message request) async {
121 : Message? messageFromProto;
122 :
123 : dynamic response;
124 :
125 : try {
126 3 : response = await methodChannel.invokeMethod(
127 : 'rpc',
128 1 : request.writeToBuffer(),
129 : );
130 : } catch (e, s) {
131 1 : log('send:', name: _tag, stackTrace: s, error: e);
132 1 : throw ChannelInvokeException();
133 : }
134 :
135 : if (response == null) {
136 1 : throw ChannelInvalidAnswerException();
137 : }
138 :
139 : try {
140 1 : messageFromProto = Message.fromBuffer(response);
141 : } catch (_) {
142 1 : throw ProtoBufferException();
143 : }
144 :
145 : return messageFromProto;
146 : }
147 :
148 1 : @override
149 : void dispose() {
150 : return;
151 : }
152 : }
|