Skip to content

Commit eb2ff7f

Browse files
authored
[tizen_rpc_port] Resolved issue with failure to receive events in multiple proxies. (#888)
Signed-off-by: Changgyu Choi <[email protected]>
1 parent 8d3cf5f commit eb2ff7f

File tree

5 files changed

+240
-63
lines changed

5 files changed

+240
-63
lines changed

packages/tizen_rpc_port/example/client/lib/main.dart

Lines changed: 102 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,22 @@ class MyApp extends StatefulWidget {
2222
}
2323

2424
class _MyAppState extends State<MyApp> {
25-
final Message _client = Message('org.tizen.tizen_rpc_port_server_example');
2625
String _message = 'Not connected';
26+
String _message2 = 'Not connected2';
2727
bool _isConnected = false;
28+
bool _isConnected2 = false;
2829
String _input = '';
30+
Message? _client;
31+
Message? _client2;
2932

3033
Future<void> _connect() async {
3134
setState(() {
3235
_message = 'Connecting...';
3336
});
3437

3538
try {
36-
await _client.connect(
39+
_client ??= Message('org.tizen.tizen_rpc_port_server_example');
40+
await _client!.connect(
3741
onError: (Object error) {
3842
setState(() {
3943
_message = 'Error: $error';
@@ -46,7 +50,7 @@ class _MyAppState extends State<MyApp> {
4650
});
4751
},
4852
);
49-
_client.register('ClientApp', onMessage);
53+
_client!.register('ClientApp', onMessage);
5054

5155
setState(() {
5256
_isConnected = true;
@@ -59,23 +63,76 @@ class _MyAppState extends State<MyApp> {
5963
}
6064
}
6165

66+
Future<void> _connect2() async {
67+
setState(() {
68+
_message2 = 'Connecting...';
69+
});
70+
71+
try {
72+
_client2 ??= Message('org.tizen.tizen_rpc_port_server_example');
73+
await _client2!.connect(
74+
onError: (Object error) {
75+
setState(() {
76+
_message2 = 'Error: $error';
77+
});
78+
},
79+
onDisconnected: () async {
80+
setState(() {
81+
_isConnected2 = false;
82+
_message2 = 'Disconnected';
83+
});
84+
},
85+
);
86+
_client2!.register('ClientApp2', onMessage2);
87+
88+
setState(() {
89+
_isConnected2 = true;
90+
_message2 = 'Connected';
91+
});
92+
} catch (error) {
93+
setState(() {
94+
_message2 = 'Error: $error';
95+
});
96+
}
97+
}
98+
6299
void onMessage(String sender, String message) {
63100
setState(() {
64101
_message = 'Received: $message';
65102
});
66103
}
67104

105+
void onMessage2(String sender, String message) {
106+
setState(() {
107+
_message2 = 'Received: $message';
108+
});
109+
}
110+
68111
Future<void> _send() async {
69112
if (_isConnected) {
70-
_client.send(_input);
113+
_client!.send(_input);
114+
}
115+
}
116+
117+
Future<void> _send2() async {
118+
if (_isConnected2) {
119+
_client2!.send(_input);
71120
}
72121
}
73122

74123
@override
75124
void dispose() {
76125
if (_isConnected) {
77-
_client.unregister();
78-
_client.disconnect();
126+
if (_client != null) {
127+
_client!.unregister();
128+
_client!.disconnect();
129+
}
130+
}
131+
if (_isConnected2) {
132+
if (_client2 != null) {
133+
_client2!.unregister();
134+
_client2!.disconnect();
135+
}
79136
}
80137
super.dispose();
81138
}
@@ -93,6 +150,10 @@ class _MyAppState extends State<MyApp> {
93150
padding: const EdgeInsets.symmetric(vertical: 20),
94151
child: Text(_message),
95152
),
153+
Padding(
154+
padding: const EdgeInsets.symmetric(vertical: 20),
155+
child: Text(_message2),
156+
),
96157
TextField(
97158
onChanged: (String text) {
98159
setState(() => _input = text);
@@ -106,13 +167,41 @@ class _MyAppState extends State<MyApp> {
106167
),
107168
),
108169
persistentFooterButtons: <Widget>[
109-
TextButton(
110-
onPressed: _isConnected ? null : _connect,
111-
child: const Text('Connect'),
112-
),
113-
TextButton(
114-
onPressed: _isConnected ? _send : null,
115-
child: const Text('Send'),
170+
Column(
171+
children: <Widget>[
172+
TextButton(
173+
style: ButtonStyle(
174+
minimumSize:
175+
MaterialStateProperty.all(const Size.fromHeight(100)),
176+
),
177+
onPressed: _connect,
178+
child: const Text('Connect'),
179+
),
180+
TextButton(
181+
style: ButtonStyle(
182+
minimumSize:
183+
MaterialStateProperty.all(const Size.fromHeight(100)),
184+
),
185+
onPressed: _connect2,
186+
child: const Text('Connect2'),
187+
),
188+
TextButton(
189+
style: ButtonStyle(
190+
minimumSize:
191+
MaterialStateProperty.all(const Size.fromHeight(100)),
192+
),
193+
onPressed: _isConnected ? _send : null,
194+
child: const Text('Send'),
195+
),
196+
TextButton(
197+
style: ButtonStyle(
198+
minimumSize:
199+
MaterialStateProperty.all(const Size.fromHeight(100)),
200+
),
201+
onPressed: _isConnected2 ? _send2 : null,
202+
child: const Text('Send2'),
203+
),
204+
],
116205
),
117206
],
118207
),

packages/tizen_rpc_port/lib/src/proxy_base.dart

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,12 @@ abstract class ProxyBase {
6161
Completer<void> _connectCompleter = Completer<void>();
6262
Completer<void> _disconnectCompleter = Completer<void>();
6363

64-
static const EventChannel _eventChannel = EventChannel(
64+
static const MethodChannel _channel = MethodChannel(
6565
'tizen/rpc_port_proxy',
6666
);
6767

68+
Stream<dynamic>? _stream;
69+
static final Set<int> _activeConnections = <int>{};
6870
StreamSubscription<dynamic>? _streamSubscription;
6971
OnDisconnected? _onDisconnected;
7072

@@ -90,14 +92,28 @@ abstract class ProxyBase {
9092
throw StateError('Proxy $appid/$portName already connected');
9193
}
9294

93-
final Stream<dynamic> stream = _eventChannel.receiveBroadcastStream(
95+
await _channel.invokeMethod(
96+
'init',
97+
<String, Object>{
98+
'handle': _handle.address,
99+
'portName': portName,
100+
},
101+
);
102+
103+
final EventChannel eventChannel = EventChannel(
104+
'tizen/rpc_port_proxy/$portName/${_handle.address}',
105+
);
106+
107+
_stream = eventChannel.receiveBroadcastStream(
94108
<String, Object>{
95109
'handle': _handle.address,
96110
'appid': appid,
97111
'portName': portName,
98112
},
99113
);
100-
_streamSubscription = stream.listen((dynamic data) async {
114+
115+
_activeConnections.add(_handle.address);
116+
_streamSubscription = _stream!.listen((dynamic data) async {
101117
final Map<String, dynamic> map =
102118
(data as Map<dynamic, dynamic>).cast<String, dynamic>();
103119
final int handle = map['handle'] as int;
@@ -114,12 +130,20 @@ abstract class ProxyBase {
114130
await _onDisconnectedEvent();
115131
await _streamSubscription?.cancel();
116132
_streamSubscription = null;
133+
_activeConnections.remove(_handle.address);
134+
if (_activeConnections.isEmpty) {
135+
_stream = null;
136+
}
117137
} else if (event == 'rejected') {
118138
_isConnected = false;
119139
final String error = map['error'] as String;
120140
await _onRejectedEvent(error);
121141
await _streamSubscription?.cancel();
122142
_streamSubscription = null;
143+
_activeConnections.remove(_handle.address);
144+
if (_activeConnections.isEmpty) {
145+
_stream = null;
146+
}
123147
} else if (event == 'received') {
124148
final Uint8List rawData = map['rawData'] as Uint8List;
125149
final Parcel parcel = Parcel.fromRaw(rawData);
@@ -182,9 +206,6 @@ abstract class ProxyBase {
182206
await _onDisconnected?.call();
183207
_onDisconnected = null;
184208

185-
getPort(PortType.main).disconnect();
186-
getPort(PortType.callback).disconnect();
187-
188209
if (!_disconnectCompleter.isCompleted) {
189210
_disconnectCompleter.complete();
190211
_disconnectCompleter = Completer<void>();

0 commit comments

Comments
 (0)