I use Flutter_blue package
When I deny access to bluetooth there is an error I can't handle. This is what shows:
This is how my code looks like:
scan() {
// Start scanning
try {
blue.startScan(timeout: const Duration(seconds: 4));
} on Exception catch (e) {
log(e.toString());
} catch (e) {
log(e.toString());
}
}
I want to handle denying permission to bluetooth. Can't handle exception error
If you use method startScan which returns a Future you can use catchError method on Future class:
blue.startScan().catchError((error) {
// handle errors here
});
If you use method scan which returns a Stream you can handle errors specifying onError parameter when calling listen method:
blue.scan(timeout: const Duration(seconds: 4)).listen((event) {
// here comes data
}, onError: (Object error){
// handle an error here
});
You can read more about the listen method here.
OR
You can use handleError method on Stream object:
blue.scan(timeout: const Duration(seconds: 4))
.handleError((error) => print('Exception caught for $error')) // handle the error
.listen((event) {
// here comes data
});
Related
My code is trying to communicate using Socket, but I can't seem to catch the exception.
I've tried these things, but they don't work and I get an exception on the IDE.
Socket socket;
try {
socket = await Socket.connect(ip, port);
// Instead of jumping to errorProcess(), the IDE will show an exception here...
} catch(e) {
errorProcess(e);
}
Socket socket = await Socket.connect(ip, port).catchError((e) {
errorProcess(e);
// catchError says we need to return FutureOr<Socket>...
});
How can I catch exceptions?
Try adding SocketException for your try catch statement.
Example Code:
try {} on SocketException catch (e) {
print(e);
} catch (e) {
print(e);
}
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 upgraded Flutter from version 2.0.2 to version 2.2.2 and now the custom exceptions that are thrown from a Future function are not being catch.
For example, I got this Future function, where I call another Future that does a server request and returns back the response or throws a custom exception (ApiException) in case of error:
static Future<bool> signUpCustomerRequest(Map<String, dynamic> params) async {
try {
// Here we call this Future function that will do a request to server API.
dynamic _response = await _provider.signUpCustomer(params);
if (_response != null) {
updateUserData(_response);
return true;
}
return false;
} on ApiException catch(ae) {
// This custom exception is not being catch
ae.printDetails();
rethrow;
} catch(e) {
// This catch is working and the print below shows that e is Instance of 'ApiException'
print("ERROR signUpCustomerRequest: $e");
rethrow;
} finally {
}
}
And this is the Future function that does the request to server and throws the ApiException:
Future<User?> signUpCustomer(Map<String, dynamic> params) async {
// POST request to server
var _response = await _requestPOST(
needsAuth: false,
path: routes["signup_client"],
formData: params,
);
// Here we check the response...
var _rc = _response["rc"];
switch(_rc) {
case 0:
if (_response["data"] != null) {
User user = User.fromJson(_response["data"]["user"]);
return user;
}
return null;
default:
print("here default: $_rc");
// And here we have the throw of the custom exception (ApiException)
throw ApiException(getRCMessage(_rc), _rc);
}
}
Before upgrading to Flutter 2.2.2 the catch of custom exceptions worked perfectly. Did something change on this Flutter version? Am I doing something wrong?
Thanks!
I was able to reproduce your bug with the following code:
class ApiException implements Exception {
void printDetails() {
print("ApiException was caught");
}
}
Future<void> doSomething() async {
await Future.delayed(Duration(seconds: 1));
throw ApiException();
}
void main() async {
try {
await doSomething();
} on ApiException catch (ae) {
ae.printDetails();
} catch (e) {
print("Uncaught error: $e"); // This line is printed
}
}
There's an open issue on the dart sdk, which I think might be related, though I'm not sure: https://github.com/dart-lang/sdk/issues/45952.
In any case, I was able to correct the error by returning a Future.error, instead of throwing the error directly:
class ApiException implements Exception {
void printDetails() {
print("ApiException was caught"); // This line is printed
}
}
Future<void> doSomething() async {
await Future.delayed(Duration(seconds: 1));
return Future.error(ApiException());
}
void main() async {
try {
await doSomething();
} on ApiException catch (ae) {
ae.printDetails();
} catch (e) {
print("Uncaught error: $e");
}
}
I'm new to Flutter & Dart, trying to complete my first app.
I can't catch (with try-catch block) http.get SocketException (which happens when you call API and WiFi turned off)
I tried everything on the internet without luck, I even tried (Dio) package to catch this exception, but no success.
How to reproduce: use bottom code...turn off phone's WiFi...call API...now the app crashes with (SocketException) in your IDE.
Image: https://imgur.com/bA0rKEN
here is my simple code (updated)
RaisedButton(
child: Text("Call API"),
onPressed: () async {
try {
http.Response response = await getLoginResponse();
//do something with response
print(response.body);
} catch (e) {
print("Button onPressed Error: " + e.toString());
}
},
)
//---------------------------------------------------------------
Future<http.Response> getLoginResponse() {
return http.get(loginUrl).timeout(Duration(seconds: 10))
.then((response) {
return response;
}, onError: (e) {
print("onError: " + e.toString());
}).catchError((err) {
print("catchError: " + err.toString());
return null;
});
}
You can catch several types of errors and handle each one separately
Example:
import 'dart:io' as Io;
http.Client client = http.Client();
try {
response = await client.get(url).timeout(new Duration(seconds: 10));
} on Io.SocketException catch (_) {
throw Exception('Not connected. Failed to load data');
} on TimeoutException catch (_) {
throw Exception('Not connected. TimeOut Exception');
} catch (e) {
// Default error handling;
}
if you want to get catch in RaisedButton's try-catch block, instead of return null in getLoginInfo() methods, you must return an Exception like this:
Future<List<LoginObject>> getLoginInfo() async {
try {
List<LoginObject> loginObjectList = List<LoginObject>();
http.Response loginResponse =
await http.get(loginUrl).timeout(Duration(seconds: 10));
if (loginResponse.statusCode == 200) {
loginObjectList = loginObjectFromJson(loginResponse.body);
return loginObjectList;
} else {
throw Exception('Authentication Error');
}
} catch (e) {
print("Error: " + e.toString());
return throw Exception('Connection Error');;
}
}
Note: If you want to handle each one of error response, you can create an custom ErrorModelClass and handle error state with it and finally return your ErrorModelClass.
catch (error) {
print(error);
throw error is HttpResponseError ? error : HttpResponseError(0,"error connection");
HttpResponseError is my custom model class.
I am trying out Dart and I've been struggling with this for quite a bit now. Calling:
runServer() {
HttpServer.bind(InternetAddress.ANY_IP_V4, 8080)
.then((server) {
server.listen((HttpRequest request) {
request.response.write('Hello, World!');
request.response.close();
});
});
}
Once works like a charm. And then, trying
try {
runServer();
} on Error catch (e) {
print("error");
} on Exception catch(f) {
print("exception");
}
Now I'd expect that if I were to use this try-catch and start listening to the same port more than once, because I'm catching ALL exceptions and ALL errors, the program wouldn't crash. However, after running the code twice, instead of entering any try/catch clause I get:
Uncaut Error: SocketException: Failed to create server socket (OS Error: Only one usage of each socket address (protocol/network address/port) is normally permitted.
While I understand what the error is, I don't understand why doesn't it simply enter the catch Error/Exception clause?
Asynchronous errors can't be caught using try/catch (https://www.dartlang.org/docs/tutorials/futures/) at least unless you are using async/await (https://www.dartlang.org/articles/await-async/)
See also https://github.com/dart-lang/sdk/issues/24278
You can use the done future on the WebSocket object to get that error, e.g.:
import 'dart:async';
import 'dart:io';
main() async {
// Connect to a web socket.
WebSocket socket = await WebSocket.connect('ws://echo.websocket.org');
// Setup listening.
socket.listen((message) {
print('message: $message');
}, onError: (error) {
print('error: $error');
}, onDone: () {
print('socket closed.');
}, cancelOnError: true);
// Add message, and then an error.
socket.add('echo!');
socket.addError(new Exception('error!'));
// Wait for the socket to close.
try {
await socket.done;
print('WebSocket donw');
} catch (error) {
print('WebScoket done with error $error');
}
}