I have problem in receiving data in flutter serial bluetooth no error in code its connected and disconnected successfully but the problem is receiving data
void listenToBluetooth() async{ // this method called in initState
try {
BluetoothConnection connection = await BluetoothConnection.toAddress(widget.address);
print('Connected to the device form listenToBluetooth method');
connection.input!.listen((Uint8List data) {
print('Data incoming: ${ascii.decode(data)}');
connection.output.add(data); // Sending data
//
// if (ascii.decode(data).contains('!')) {
// connection.finish(); // Closing connection
// print('Disconnecting by local host');
// }
}).onDone(() {
print('Disconnected by remote request');
});
}
catch (exception) {
print('Cannot connect, exception occurred');
}
}
Related
I want to update the UI when I receive background notification from Firebase.
I have a backgroundMessage handler
`
#pragma('vm:entry-point')
Future<void> handleBackgroundNotification(RemoteMessage remoteMessage) async {
try {
final SendPort send = IsolateNameServer.lookupPortByName('port_firebase');
send.send(remoteMessage.notification.body);
} catch (e) {
log(e.toString());
throw e;
}
}
And I am registering my Receive port and background handler insideinitState`.
bool res = IsolateNameServer.registerPortWithName(
_port.sendPort, 'port_firebase');
log('status $res');
if (res) {
log('port created successfuly');
_port.listen((dynamic data) {
log('port ' + data.toString());
}, onError: (e) {
log('error is ${e.toString()}');
});
}
FirebaseMessaging.onBackgroundMessage(handleBackgroundNotification);
It registers the port successfully but whenever I receive background notification. It gives me error
NoSuchMethodError: The method 'send' was called on null.
Receiver: null
Tried calling: send("Welocme to FCM")
Does anyone have solution to this problem.
Add await in this line
final SendPort send = await IsolateNameServer.lookupPortByName('port_firebase');
I've initialized a WebSocket connection and I'm listening to stream which I've defined as asBroadcastStream so it does not return stream has already been listened to listening for events from same stream.
Stream is listening to same message multiple times.
For example
On 1st message
Stream prints data 1 time
On 2nd message
Stream prints data 2 times
On 3rd message
Stream prints data 3 times
... and so on.
class NotificationController {
static final NotificationController _singleton =
NotificationController._internal();
StreamController<String> streamController =
StreamController.broadcast(sync: true);
IOWebSocketChannel? channel;
late var channelStream = channel?.stream.asBroadcastStream();
factory NotificationController() {
return _singleton;
}
NotificationController._internal() {
initWebSocketConnection();
}
initWebSocketConnection() async {
var storedUserInfo = storage.getUserInfoStorage();
Map storedData = await storedUserInfo;
String userID = storedData['user_id'];
print("conecting...");
try {
channel = IOWebSocketChannel.connect(
Uri.parse('ws://127.0.0.1:8001/chat/$userID/'),
pingInterval: const Duration(seconds: 10),
);
} on Exception catch (e) {
print(e);
return await initWebSocketConnection();
}
print("socket connection initializied");
channel?.sink.done.then((dynamic _) => _onDisconnected());
}
void sendMessage(messageObject, Function messageListener) {
try {
channel?.sink.add(json.encode(messageObject));
var mystream = channelStream?.listen((data) {
print(data);
Map message = json.decode(data);
messageListener(message);
});
} on Exception catch (e) {
print(e);
}
}
void _onDisconnected() {
initWebSocketConnection();
}
}
You may be initializing the listener multiple times.
put your code where your initialized code is called only once may be initState method or globally.
A server that will keep a permanent connection via Tcp. And close when the program is shut down.
An example of connecting a server that reconnects every time:
class Server {
void connectToServer() async {
try {
Socket _socket = await Socket.connect('127.0.0.1', 7890);
log('connected: ${_socket.address}:${_socket.port}');
} catch (e) {
log(e.toString());
}
}
void send(temp) async {
Socket _socket = await Socket.connect('127.0.0.1', 7890);
_socket.listen((List<int> event) {
log(utf8.decode(event));
});
_socket.add(utf8.encode(temp));
}
}
I am using dio 4.0.2. The problem is that when there is no internet connection(when internet and wifi is not turned on), SocketException: Failed host lookup is not being caught. I checked via interceptor's onError method and I am sure it is sending error from interceptor. But post request is not throwing error for this.
Here is my interceptor on error code:
#override
void onError(DioError err, ErrorInterceptorHandler handler) {
super.onError(err, handler);
}
How can I catch this?
I'm using it like this:
bool _isServerDown(DioError error) {
return (error.error is SocketException) || (error.type == DioErrorType.connectTimeout);
}
#override
Future<void> onError(DioError error, ErrorInterceptorHandler handler) async {
if (_isServerDown(error)) {
Response? response;
try {
response = await tryAnotherUrl(error.requestOptions);
} catch (error) {
if (error is DioError) {
response = error.response;
handler.next(error);
return;
}
}
if (response != null) {
handler.resolve(response);
} else {
handler.next(error);
}
return;
}
Not sure why, but this worked for me:
// add error interceptor to catch all errors
dioBuilder.dio.interceptors.add(
InterceptorsWrapper(
onError: (error, handler) {
// Do stuff here
handler.reject(error); // Added this line to let error propagate outside the interceptor
},
),
);
I'm implementing socket.
Two clients connect to the server with no problem, when client1 sends a message to the server, the server publishes it to every other client (which in this case is client2). but client2 won't get the message unless it sends a message. It seems the listener of the client doesn't work. Obviously, I want client2 to get the message from client1 instantly.
here is my sever code:
import 'dart:io';
import 'dart:typed_data';
void main() async {
// bind the socket server to an address and port
MySocket mySocket = MySocket();
await mySocket.init();
}
class MySocket {
ServerSocket? server;
List<Socket> clients = [];
//initialize the socket
init() async {
server = await ServerSocket.bind("192.168.0.112", 4000);
// listen for client connections to the server
server!.listen((client) {
handleConnection(client);
addClient(client);
});
}
void handleConnection(Socket client) async {
print('Connection from'
' ${client.remoteAddress.address}:${client.remotePort}');
// listen for events from the client
client.listen(
// handle data from the client
(Uint8List data) async {
await Future.delayed(Duration(seconds: 1));
final message = String.fromCharCodes(data);
print(message);
publish(message, client);
},
// handle errors
onError: (error) {
print(error);
client.close();
},
// handle the client closing the connection
onDone: () {
print('Client left');
client.close();
},
);
}
void addClient(Socket client) {
//if client doesn't already exist add it to the list of clients
if (!clients.any((element) =>
'${client.remoteAddress.address}:${client.remotePort}' ==
'${element.remoteAddress.address}:${element.remotePort}')) {
clients.add(client);
}
}
void publish(String message, Socket client) {
//write the message to every client except the author of it
clients.forEach((element) async {
if ('${client.remoteAddress.address}:${client.remotePort}' !=
'${element.remoteAddress.address}:${element.remotePort}') {
element.write(message);
}
});
}
}
here is my client-side code:
import 'dart:io';
import 'dart:typed_data';
void main() async {
//gets the username
String name = '';
while (name.isEmpty) {
print('Enter your name: ');
name = stdin.readLineSync() ?? '';
}
// connect to the socket server
final socket = await Socket.connect("192.168.0.112", 4000);
print('Connected to: ${socket.remoteAddress.address}:${socket.remotePort}');
// listen for responses from the server
socket.listen(
// handle data from the server
(Uint8List data) {
final serverResponse = String.fromCharCodes(data);
print('$serverResponse');
},
// handle errors
onError: (error) {
print(error);
socket.destroy();
},
// handle server ending connection
onDone: () {
print('Left server.');
socket.destroy();
},
);
// sending messages to the server
String message = "";
while (message != "exit") {
message = stdin.readLineSync() ?? '';
await sendMessage(socket, name, message);
}
socket.close();
}
Future<void> sendMessage(Socket socket, String name, String message) async {
socket.write('$name: $message');
await Future.delayed(Duration(seconds: 2));
}
Thank you in advance.
The issue is because stdin.readLineSync() in your client blocks the current thread. You can get around this by spawning an isolate to handle that portion of the code, so that it does not block the socket.listen from printing out the responses from the server.
See updated client code below:
import 'dart:io';
import 'dart:isolate';
import 'dart:typed_data';
void main() async {
//gets the username
String name = '';
while (name.isEmpty) {
print('Enter your name: ');
name = stdin.readLineSync() ?? '';
}
// connect to the socket server
final socket = await Socket.connect("192.168.0.112", 4000);
print('Connected to: ${socket.remoteAddress.address}:${socket.remotePort}');
// listen for responses from the server
socket.listen(
// handle data from the server
(Uint8List data) {
final serverResponse = String.fromCharCodes(data);
print('$serverResponse');
},
// handle errors
onError: (dynamic error) {
print(error);
socket.destroy();
},
// handle server ending connection
onDone: () {
print('Left server.');
socket.destroy();
},
);
final receive = ReceivePort();
final isolate = await Isolate.spawn(readMessages, receive.sendPort);
await for (final message in receive) {
if (message == 'exit') break;
await sendMessage(socket, name, message as String);
}
socket.close();
}
void readMessages(SendPort port) {
String message = '';
while (message != 'exit') {
message = stdin.readLineSync() ?? '';
port.send(message);
}
Isolate.exit(port);
}
Future<void> sendMessage(Socket socket, String name, String message) async {
socket.write('$name: $message');
await Future<void>.delayed(Duration(seconds: 2));
}