I'm trying to learn Flutter/Dart and I'm having to much problems. Now I'm trying to obtain some values from an API. My code is:
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:myapp01_apirequest/src/models/uplink_models.dart';
class UplinksProvider{
String _url = 'https://xxx.yyy.com:14442/api/external/';
Future<List<Uplink>> getEnCines() async{
try{
final url = Uri.https(_url, 'login', {
'username': 'Joe689',
'password': '15.Job_1825zz'
});
final resp = await http.get(url);
final decodedData = json.decode(resp.body);
print('Patata');
print(decodedData);
return [];
}catch (error){
print('++++++++++///////++++++++++++++++');
print(error);
print('++++++++++*******++++++++++++++++');
}
}
}
With the try/catch I obtain this error:
I/flutter ( 3714): ++++++++++///////++++++++++++++++
I/flutter ( 3714): FormatException: Invalid radix-10 number (at character 1)
I/flutter ( 3714): //xxx.yyy.com:14442/api/external/
I/flutter ( 3714): ^
I/flutter ( 3714): ++++++++++*******++++++++++++++++
I found a lot of posts asking the same, for example this one, but I'm not sure to understand it.
My idea is that I'm receiving a bad response, with a bad encoding, but I don't know how to solve it.
Can somebody help me?
Thank you very much.
Remove https:// from your URL.
See the docs. You aren't supposed to include the scheme. That's why you call Uri.https.
Related
I'd like to download the JSON file which can be accessed by this url https://firebasestorage.googleapis.com/v0/b/prufungssimulation-caff9.appspot.com/o/5qPfjoZjdNXyN5Ob2q3pFbj5MKy1.json?alt=media. Every time I call the function I get a Error: XMLHttpRequest error. After some researches I found that this might be beacuase Google Firebase Storage is blocking it. Does anybody know how to avoid this block? I've read that I should whiltlist my local host? But how?
headers: {
HttpHeaders.authorizationHeader: 'Basic your_api_token_here', //here i want my token
},
But I have no clue how to get my api Token. Does anybody know how to fetch this token? May this error be caused becaus I run it on chrom flutter?
import 'package:http/http.dart' as http;
void testFunction(){
var url_string = "https://firebasestorage.googleapis.com/v0/b/prufungssimulation-caff9.appspot.com/o/5qPfjoZjdNXyN5Ob2q3pFbj5MKy1.json?alt=media";
var result = await getJsonFromFirebaseRestAPI(url_string);
print(result);
}
Future<String> getJsonFromFirebaseRestAPI(String url) async {
http.Response response = await http.get(Uri.parse(url));
return response.body;
}
The JSON file result should look like this:
routes: []
It's basically empty I'm just trying to implement the function.
I use http: ^0.13.5
I get the following error:
Error: XMLHttpRequest error.
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 299:10
createErrorWithStack
dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 341:28
_throw
dart-sdk/lib/core/errors.dart 116:5
throwWithStackTrace
dart-sdk/lib/async/zone.dart 1378:11
callback
dart-sdk/lib/async/schedule_microtask.dart 40:11
_microtaskLoop
dart-sdk/lib/async/schedule_microtask.dart 49:5
_startMicrotaskLoop
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 166:15
<fn>
``
Can anybody solve my issue?
Appreciate your time :)
I have been having a huge failure working with FormData using flutter. It works fine while I tested with postman which tells me the error is from my end. I need to post some list of files to the backend along with some parameters as such.
But it gives me 501 error each time which tells me that some data is invalid, however, there is no way to tell me exactly which parameter the error is located.
Dio dio = new Dio();
List<Map<String, int>> scheduled_slots = [
{"dateslot_id": 107, "timeslot_id": 97},
{"dateslot_id": 121, "timeslot_id": 120}
];
List<String> filesPath = ["/data/user/0/com.heckerbella.hope_clinic/app_flutter/1634521427103972"];
List<String> filesName = ["fileName"];
List<String> type =["Burning Pain", "Burning Pain"];
List<String> rating =["Just curious", "Mild Pain"];
FormData formData = FormData.fromMap({
"type": type,
"rating": rating,
"description": widget.description,
'files': [
await files.asMap().forEach((index, value) async {
await MultipartFile.fromFile
(filesPath[index], filename:
filesName[index]);
}),],
"scheduled_slots": scheduled_slots as String
});
try {
Response response = await dio.post(
Constants().API_BASE_URL +
"scheduled/slot/main/create/${selectedPlansData.id}",
data: formData,
options: Options(responseType: ResponseType.json, headers: {
"Authorization": "Bearer ${bloc.bearerToken}",
"Accept": "application/json",
}));
AlertManager.showToast(response.data.toString());
print(Constants().API_BASE_URL +
"scheduled/slot/main/create/${selectedPlansData.id}");
return response.data;
} catch (e) {
print(e.toString());
}
}
Error
I/flutter (10345): DioError [DioErrorType.response]: Http status error [501]
I/flutter (10345): #0 DioMixin.assureDioError (package:dio/src/dio_mixin.dart:819:20)
I/flutter (10345): #1 DioMixin._dispatchRequest (package:dio/src/dio_mixin.dart:678:13)
I/flutter (10345): <asynchronous suspension>
I/flutter (10345): #2 DioMixin.fetch.<anonymous closure>.<anonymous closure> (package:dio/src/dio_mixin.dart)
I/flutter (10345): <asynchronous suspension>
D/CompatibilityChangeReporter(10345): Compat change id reported: 147798919; UID 10146; state: ENABLED
E/Toast (10345): setGravity() shouldn't be called on text toasts, the values won't be used
You have issue with scheduled_slots, Dio only support fields on FormData is String, so when you pass a value is List<Map<String, int>>, Server will not receive it. Let deal with BE to convert scheduled_slots from List -> String.
I have been trying to launch a URL insder the flutter app. I am using url_launcher but am unable to launch the URL. The URL that I am receiving is a response from an API.
If I am copying the response and sending it statically, it's working, but when passing as a dynamic variable, it always shows "Could not be launched."
Code:
checkoutCartItem() async {
var url = Uri.parse(
'');
final headers = {'Content-Type': 'application/json'};
var body = jsonEncode({
"status": 2,
"uid": SignForm.userIdGlobal,
});
final encoding = Encoding.getByName('utf-8');
Response response = await post(
url,
headers: headers,
body: body,
encoding: encoding,
);
print(response.body);
Body.url = response.body.toString();
print(Body.url);
if (await canLaunch(Body.url.toString())) {
await launch(Body.url.toString());
} else {
throw 'Could not launch $Body.url';
}
}
Flutter version: 2.2,
url_launcher: ^6.0.4
Error:
[VERBOSE-2:ui_dart_state.cc(199)] Unhandled Exception: Could not launch [TextElement: '
', LinkElement: 'https://www.bsestarmf.in/ClientOrderPayment.aspx?K4HhW6zSxVp2T2sl9n5acA+J8qCjHcdVy2hyQmgbsuje2e6rf0+sujJisssdsaBFQV1zicfCer4VQUqJtRxgRiLYXwfXKkOBj9pA5dqrlOiLEPkxgWpB0QQa36DMiHhyqCA/fP60nFus9nGlM='
print(response.body)
Gives:
https://www.bsestarmf.in/ClientOrderPayment.aspx?K4HhW6zSxVp2T2sl9n5acA+J8qCjHcdVy2hyQmgbsuje2e6rf0+sujJiBFQV1zicfCer4VQUqJtRxgRiLYXwfXKkOBj9dddddpA5dqrlOiLEPkxgWpB0QQa36DMiHhyqCA/fP60nFus9nGlM=
[VERBOSE-2:ui_dart_state.cc(199)] Unhandled Exception: Could not launch Body.url
#0 checkoutCartItem (package:optymoney/Cart/Components/Body.dart:58:5)
<asynchronous suspension>
#1 _BodyState.build.<anonymous closure>.<anonymous closure> (package:optymoney/Cart/Components/Body.dart:326:29)
<asynchronous suspension>
This is a payment link that should open a browser inside the flutter app. But it's now working.
Please help!!!
N.B: Since this is a payment link, it has been edited and so it won't work if you try launching it from a browser
final payUrl = Uri.encodeFull(response.body);
if (await canLaunch(payUrl)) {
await launch(payUrl, forceWebView: true, enableJavaScript: true);
} else {
throw 'Could not launch $payUrl';
}
This is how I resolved the issues. Turns out that encoding the received response was the solution needed.
We are using GraphQL to connect our backend with our mobil application. We are using Riverpod to, among other things, handle global state, dependency injection, etc.
We are using a provider to handle the GraphQL cliente without any authentication header at first while the user is not authentication (this will handle unauthenticated request like login or registering), after the user is authenticated, a token provider who provides the token is updated and it must update the client provider who is user for every repository on the application:
final StateProvider<String> tokenProvider =
StateProvider<String>((_) => '', name: "Token Provider");
final graphQLClientProvider = Provider<GraphQLClient>(
(ref) {
final String token = ref.watch(tokenProvider).state;
final Link _link = HttpLink(
'http://192.168.1.36:1337/graphql',
defaultHeaders: {
if (token != '') 'Authorization': 'Bearer $token',
});
return GraphQLClient(
cache: GraphQLCache(),
link: _link,
);
},
name: "GraphQL Client Provider",
);
There is too problems here:
After updating the token, the client is changed, and from this, the function who updates the token does not finish in a proper way:
[ +141 ms] E/flutter ( 8361): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: Bad state: Tried to use AuthNotifier after `dispose` was called.
[ ] E/flutter ( 8361):
[ ] E/flutter ( 8361): Consider checking `mounted`.
[ ] E/flutter ( 8361):
[ ] E/flutter ( 8361): #0 StateNotifier._debugIsMounted.<anonymous closure> (package:state_notifier/state_notifier.dart:128:9)
[ ] E/flutter ( 8361): #1 StateNotifier._debugIsMounted (package:state_notifier/state_notifier.dart:135:6)
[ ] E/flutter ( 8361): #2 StateNotifier.state= (package:state_notifier/state_notifier.dart:155:12)
[ ] E/flutter ( 8361): #3 AuthNotifier.signIn (package:thesis_cancer/features/auth/application/auth.notifier.dart:84:7)
[ ] E/flutter ( 8361): <asynchronous suspension>
[ ] E/flutter ( 8361): #4 _LoginCardState._submit (package:flutter_login/src/widgets/auth_card.dart:503:15)
[ ] E/flutter ( 8361): <asynchronous suspension>
[ ] E/flutter ( 8361):
It means when the token is updated, the authentication notifier who receives the repository with depends on the provided client is updated/changes (following the chain):
final authRepositoryProvider = Provider<AuthRepository>(
(ref) => GraphQLAuthRepository(client: ref.read(graphQLClientProvider)),
name: 'Auth Repository Provider',
);
final authNotifierProvider = StateNotifierProvider<AuthNotifier, AuthState>(
(ref) => AuthNotifier(
authRepository: ref.watch(authRepositoryProvider),
dataStore: ref.watch(dataStoreRepositoryProvider),
profileRepository: ref.watch(profileRepositoryProvider),
tokenController: ref.watch(tokenProvider.notifier),
userController: ref.watch(userEntityProvider.notifier),
),
name: "Authentication Notifier Provider",
);
The notification function who breaks at the conditional(if):
Future<String?> signIn({
required String username,
required String password,
}) async {
try {
final Map<String, dynamic> rawUser = await authRepository.signIn(
identifier: username, password: password) as Map<String, dynamic>;
final User sessionUser = User.fromJson(rawUser);
if (sessionUser.confirmed != false) {
tokenController.state = sessionUser.token!; <-- Bug begins here
}
await dataStore.writeUserProfile(sessionUser);
userController.state = sessionUser;
state = const AuthState.loggedIn();
} on LogInFailureByBadRequest {
return "E-posta veya şifre geçersiz.";
} on LogInFailure catch (error) {
return error.toString();
}
}
While the client appears to be changed when the token is updated, the client itself does not reflect the change (it does not include the authentication header with the token) and thus breaks the GraphQL client:
Following the comments on the issue we opened, we added the ProviderReference to our notifier (following this question) but it does not work:
AuthNotifier(
this._ref, {
required this.authRepository,
required this.profileRepository,
required this.dataStore,
required this.tokenController,
required this.userController,
}) : super(const AuthState.loading());
final ProviderReference _ref;
final ProfileRepository profileRepository;
final AuthRepository authRepository;
final DataStoreRepository dataStore;
final StateController<User?> userController;
final StateController<String> tokenController;
At this point, we don't understand what's the problem here.
UPDATE
We removed this changes both in the StateNotifier and its provider.
Getting the client at repository by read does not avoid the error:
What's the proper way to handle the authorization token and the GraphQL client with Riverpod?
Thank you.
The problem is the authRepositoryProvider:
final authRepositoryProvider = Provider<AuthRepository>(
(ref) => GraphQLAuthRepository(client: ref.read(graphQLClientProvider)),
name: 'Auth Repository Provider',
);
In this fragment, the authRepositoryProvider is using a GraphQLClient without token. When the token is updated, the graphQLClientProvider state is well updated, but the authRepositoryProvider isn't because you are using ref.read avoiding the rebuild of the authRepositoryProvider state. This implies that the authRepositoryProvider knows a disposed (and unmounted) state of graphQLClientProvider and that's why the error message.
There are 2 solutions:
Using ref.watch:
final authRepositoryProvider = Provider<AuthRepository>(
(ref) => GraphQLAuthRepository(client: ref.watch(graphQLClientProvider)),
name: 'Auth Repository Provider',
);
Passing the ref.read as parameter:
final authRepositoryProvider = Provider<AuthRepository>(
(ref) => GraphQLAuthRepository(client: ref.read),
name: 'Auth Repository Provider',
);
class AuthRepository {
AuthRepository(this.read)
final Reader read;
GraphQLClient get client => read(graphQLClientProvider);
}
Be care about using read and watch, the first one does not react to the changes but could be used anywhere, while the second one reacts to a provider's state update but only can be used in another provider constructor or in a widget that provides access to a watch or ref.watch depending on the version of Riverpod.
In addition, there is another problem in your code:
final User sessionUser = User.fromJson(rawUser);
if (sessionUser.confirmed != false) {
// In this moment, the token is updated,
// then the QrahpQLClient is updated,
// then the AuthNotifier is recreated,
// i.e the current is disposed
// and now becomes the previous
tokenController.state = sessionUser.token!; <-- Bug begins here
}
await dataStore.writeUserProfile(sessionUser);
userController.state = sessionUser;
// In this moment you are updating the state of a disposed notifier
state = const AuthState.loggedIn();
To provide a solution it is necessary to define which elements will make rebuild the AuthNotifer.state instead of recreating the notifier.
You must consider access to another notifiers bases on the ref.read and manually create the subscriptions in the StateController constructor.
In the future, when riverpod 1.0 will be released, this issue will be easy with ref.listen but now you need to rewrite your code. You can take inspiration in the bloc-to-bloc communication gide: https://bloclibrary.dev/#/architecture?id=bloc-to-bloc-communication
i think the error is in your AuthNotifier:
if (sessionUser.confirmed != false) {
tokenController.state = sessionUser.token!; <-- you are updating a dependencie of your actual AuthNotifier object
}
await dataStore.writeUserProfile(sessionUser); <-- during the await a new object is created and the actual instance is disposed so this line will throw
I wrote the below code that reads a tring from URL, writting the cotent into a file data.csv then trying to open the file to read its contents as csv but got an error that:
I/flutter ( 6145): FileSystemException: Cannot open file, path =
'data.csv' (OS Error: No such file or directory, errno = 2) I/flutter
( 6145): File is now closed. E/flutter ( 6145):
[ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception:
FileSystemException: Cannot open file, path = 'data.csv' (OS Error:
Read-only file system, errno = 30)
My code is:
import 'dart:convert';
import 'dart:io';
import 'dart:async';
void _incrementCounter() {
setState(() {
new HttpClient().getUrl(Uri.parse('https://docs.google.com/spreadsheets/d/e/2PACX-1vQvf9tp4-fETDJbC-HRmRKvVFAXEAGO4lrYPpVeiYkB6nqqXdSs3CjX0eBMvjIoEeX9_qU6K2RWmzVk/pub?gid=0&single=true&output=csv'))
.then((HttpClientRequest request) => request.close())
// .then((HttpClientResponse response) => response.transform(new Utf8Decoder()).listen(print));
.then((HttpClientResponse response) => response.pipe(new File('data.csv').openWrite()));
final File file = new File("data.csv");
Stream<List> inputStream = file.openRead();
inputStream
.transform(utf8.decoder) // Decode bytes to UTF-8.
.transform(new LineSplitter()) // Convert stream to individual lines.
.listen((String line) { // Process results.
List row = line.split(','); // split by comma
String city = row[0];
String branches = row[1];
print('$city, $branches');
},
onDone: () { print('File is now closed.'); },
onError: (e) { print(e.toString()); });
// List<List<dynamic>> rowsAsListOfValues = const CsvToListConverter().convert(yourString);
_counter++;
});
}
Your code are not running in the order that you think so you will end up trying to read the file before it has been written. I think you code is going to be easier to understand if you use my answer for a other question you have asked: Reading data from url in List
And again, please read: https://dart.dev/codelabs/async-await