I am getting this error in flutter when I am making my login page, I am sure that the server is returning JSON not HTML but I am still getting the error. I have even tried using some "test" links and I am getting the same error.
E/flutter (25538): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: FormatException: Unexpected character (at character 1)
E/flutter (25538): <br />
E/flutter (25538): ^
E/flutter (25538):
This is my code
Future userLogin() async {
setState(() {
visible = true;
});
String email = emailController.text;
String password = passwordController.text;
var url = 'http://192.168.1.2/***************/*********.php';
var data = {'email': email, 'password': password};
var response = await http.post(Uri.parse(url), body: json.encode(data));
var message = jsonDecode(response.body);
if (message == 'Login Matched') {
// Hiding the CircularProgressIndicator.
setState(() {
visible = false;
});
Navigator.push(
context, MaterialPageRoute(builder: (context) => StageOne()));
} else {
setState(() {
visible = false;
});
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text(message),
actions: <Widget>[
FlatButton(
child: new Text("OK"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
}
Related
I was working with rest api in flutter but I get error when I want create post options. I created task with post. I want solve this error. I have given the necessary code structures in the description. I hope I was able to explain clearly
Code Here:
My BaseClientClass
Future<dynamic> post(String baseUrl, String api, dynamic payloadObj) async {
var uri = Uri.parse(baseUrl + api);
String payload = json.encode(payloadObj);
try {
var response = await http.post(uri, body: payload, headers: {
'Content-Type': 'application/json'
}).timeout(const Duration(seconds: TIME_OUT_DURATION));
return _procosessResponse(response);
} on SocketException {
throw FetchDataException('No Internet connection', uri.toString());
} on TimeoutException {
throw ApiNotRespondingException(
'API not responded in time', uri.toString());
}
}
Controller class
Future postTodo(String task, bool active) async {
Map msg = {
"task": task,
"active": active
};
// String jsonS= json.encode(msg);
var response = await baseClient.post(
"http://192.168.1.114:5000", '/api/task', msg);
if (response.statusCode == 200 || response.statusCode == 201) {
var jsonData = json.decode(response.body);
if (jsonData['success']) { // eğer succes true ise
todolist.add(TodoModel.fromJson(jsonData['data']));
// var jsonData = json.encode(response);
print(msg);
}
}
add task Widget class
class AddTaskWidget extends StatelessWidget {
TextEditingController? task;
VoidCallback? onPress;
AddTaskWidget({this.task, this.onPress});
#override
Widget build(BuildContext context) {
return Container(
child: AlertDialog(
content: TextFormField(
controller: task,
),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text("İptal")),
TextButton(onPressed: onPress, child: Text("Ekle"))
],
),
);
}
}
This call post function and task widget code
IconButton(
onPressed: () => showDialog(
context: context,
builder: (context) => AddTaskWidget(
task: todoController.textTaskNameController,
onPress: () async{
await todoController.postTodo(
todoController.textTaskNameController.text, true);
Navigator.pop(context);
}),
),
icon: Icon(Icons.add))
Provide the API response payload once in JSON format
I'm using a Rest API to call a GET method to fetch some Data. I'm doing this to load a profile to view inside my flutter body. I'm trying to assign these data to String variables inside the FutureBuilder method .
In the future builder , the fetchUser() API call response should be returning, but the snapshot returns a null. and so when ever I try to run this, the screen is stuck in the CircularProgressIndicator.
can someone help me to figure this out where I'm doing this wrong and how to solve it?
The body in flutter page
final userProfileView = FutureBuilder<UserFetch>(
future: CallApi().fetchUser(apiUrl),
builder: (context, snapshot) {
if(!snapshot.hasData)//(!snapshot.hasData)
return Center(
widthFactor: 120.0,
heightFactor: 120.0,
child: CircularProgressIndicator(),
);
// final userD = snapshot.data;
_userName = snapshot.data.user.username.toString();
_userEmail = snapshot.data.user.email;
_userAddress = snapshot.data.user.address.toString();
_userPassword = 'password';
_userCountry = 'country';
_userMobile = snapshot.data.user.mobile.toString();
//checks if the response returns valid data
return Container(
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
child: SingleChildScrollView(
child: Column(
children: <Widget>[
userTitle,
SizedBox(height: 12.0),
userNameTitle,
userName,
SizedBox(height: 12.0),
userEmailTitle,
userEmail,
SizedBox(height: 12.0),
userPasswordTitle,
userPassword,
SizedBox(height: 12.0),
userAddressTitle,
userAddress,
SizedBox(height: 12.0),
userCountryTitle,
userCountry,
SizedBox(height: 12.0),
userPhoneTitle,
userPhone,
SizedBox(height: 24.0),
userLogoutBtn,
],
),
),
),
);
// } else if (snapshot.hasError) {
// //checks if the response throws an error
// return Text("${snapshot.error}");
// }
});
The Api Call
Future<UserFetch> fetchUser(apiUrl) async {
var fullUrl = _baseUrl + apiUrl;
final response = await http.get(fullUrl, headers: _setHeaders());
if (response.statusCode == 200) {
// If the call to the server was successful (returns OK), parse the JSON.
return UserFetch.fromJson(json.decode(response.body));
} else {
// If that call was not successful (response was unexpected), it throw an error.
throw Exception('Failed to load User');
}
}
The Response Model
UserFetch userFetchFromJson(String str) => UserFetch.fromJson(json.decode(str));
String userFetchToJson(UserFetch data) => json.encode(data.toJson());
class UserFetch {
UserFetch({
this.success,
this.user,
});
bool success;
User user;
factory UserFetch.fromJson(Map<String, dynamic> json) => UserFetch(
success: json["success"],
user: User.fromJson(json["user"]),
);
Map<String, dynamic> toJson() => {
"success": success,
"user": user.toJson(),
};
}
class User {
User({
this.email,
this.address,
this.imperial,
this.mobile,
this.petsInfo,
this.role,
this.subscribed,
this.username,
});
String email;
String address;
bool imperial;
String mobile;
List<PetsInfo> petsInfo;
String role;
bool subscribed;
String username;
factory User.fromJson(Map<String, dynamic> json) => User(
email: json["email"],
address: json["address"],
imperial: json["imperial"],
mobile: json["mobile"],
petsInfo: List<PetsInfo>.from(json["pets_info"].map((x) => PetsInfo.fromJson(x))),
role: json["role"],
subscribed: json["subscribed"],
username: json["username"],
);
Map<String, dynamic> toJson() => {
"email": email,
"address": address,
"imperial": imperial,
"mobile": mobile,
"pets_info": List<dynamic>.from(petsInfo.map((x) => x.toJson())),
"role": role,
"subscribed": subscribed,
"username": username,
};
}
class PetsInfo {
PetsInfo({
this.id,
this.name,
});
int id;
String name;
factory PetsInfo.fromJson(Map<String, dynamic> json) => PetsInfo(
id: json["id"],
name: json["name"],
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
};
}
The Logs when user profile page called
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
'package:flutter/src/widgets/framework.dart': Failed assertion: line 273 pos 18: '_registry.containsKey(key)': is not true.
════════════════════════════════════════════════════════════════════════════════════════════════════
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following assertion was thrown while finalizing the widget tree:
'package:flutter/src/widgets/framework.dart': Failed assertion: line 273 pos 18: '_registry.containsKey(key)': is not true.
Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
https://github.com/flutter/flutter/issues/new?template=BUG.md
When the exception was thrown, this was the stack:
#2 GlobalKey._debugVerifyIllFatedPopulation.<anonymous closure> (package:flutter/src/widgets/framework.dart:273:18)
#3 GlobalKey._debugVerifyIllFatedPopulation (package:flutter/src/widgets/framework.dart:298:6)
#4 BuildOwner.finalizeTree.<anonymous closure> (package:flutter/src/widgets/framework.dart:2769:21)
#5 BuildOwner.finalizeTree (package:flutter/src/widgets/framework.dart:2849:8)
#6 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:915:18)
use future type to API call function because it is not decided that what is coming in future like this
Future<dymamic> fetchUser(apiUrl) async {
var fullUrl = _baseUrl + apiUrl;
final response = await http.get(fullUrl, headers: _setHeaders());
if (response.statusCode == 200) {
// If the call to the server was successful (returns OK), parse the JSON.
return UserFetch.fromJson(json.decode(response.body));
} else {
// If that call was not successful (response was unexpected), it throw an error.
throw Exception('Failed to load User');
}
}
now check the response in FutureBuiler whether it throws an error or not.
if(snapshot.data=="Failed to load User"){
return Text("something went wrong");
}
as I am new to the flutter, I came across the following exception while making a test app with the HTTP module and can't seem to find a solution around. Can anyone suggest a solution?
Future addProduct(Product product) {
const url = 'wrong_url_that_throws_format_error';
return http
.post(
url,
body: json.encode({
'title': product.title,
'description': product.description,
'imageUrl': product.imageUrl,
'price': product.price,
'isFavorite': product.isFavorite,
}),
).then((response) {
// Do things if successful
}).catchError((error) {
throw error;
});
}
// And in the widget
addProduct(_editedProduct).catchError((_) {
// this return will throw exception saying:
// Unhandled Exception: type 'Future<dynamic>' is not a subtype of type 'FutureOr<Null>'
return showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: const Text('Oops'),
content: const Text('Something went wrong.'),
actions: <Widget>[
FlatButton(
child: const Text('Ok'),
onPressed: () {
Navigator.of(ctx).pop();
},
),
],
),
);
}).then((_) {
setState(() {
_isLoading = false;
});
Navigator.of(context).pop();
});
According to the error message, the returned type was Future(dynamic), while the expected returning type was a FutureOr(Null). As the message says, FutureOr<Null> isn't a subtype of Future<dynamic>.
You can fix that by specifying the returning type of showDialog, so it returns the right type. Instead of:
return showDialog(...)
use:
return showDialog<Null>(...)
Unexpected characters  showing up when I decoding json
E/flutter (27537): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: FormatException: Unexpected character (at character 1)
E/flutter (27537): {"data":[{"kode_wilayah":"056001 ","nama":"Kec. Karang Pilang","mst_kod...
E/flutter (27537): ^
E/flutter (27537):
E/flutter (27537): #0 _ChunkedJsonParser.fail (dart:convert-patch/convert_patch.dart:1392:5)
Here is the code
Future<List<Kecamatan>> getData() async {
List<Kecamatan> list;
String link =
"http://jendela.data.kemdikbud.go.id/api/index.php/CWilayah/wilayahGET/?mst_kode_wilayah=056000";
var res = await http
.get(Uri.encodeFull(link), headers: {"Accept": "application/json;charset=UTF-8", "Charset": "utf-8"});
print(res.body);
if (res.statusCode == 200) {
var data = json.decode(res.body);
var rest = data["data"] as List;
print(rest);
list = rest.map<Kecamatan>((json) => Kecamatan.fromJson(json)).toList();
}
print("List Size: ${list.length}");
return list;
}
//inside build function
final kec = FutureBuilder<List<Kecamatan>>(
future: getData(),
builder: (BuildContext context,
AsyncSnapshot<List<Kecamatan>> snapshot) {
if (!snapshot.hasData) return CircularProgressIndicator();
return DropdownButton<Kecamatan>(
items: snapshot.data
.map((camat) => DropdownMenuItem<Kecamatan>(
child: Text(camat.nama),
value: camat,
))
.toList(),
onChanged: (Kecamatan value) {
setState(() {
_selectedKec = value;
});
},
isExpanded: false,
//value: _currentCamat,
hint: Text('Pilih Kecamatan'),
);
});
Anybody know how to remove those characters? or maybe you can show me another method to create dropdown menu based on json?
You can do this in such a way:
if (res.statusCode == 200) {
// <============
final prefix = '';
var body = res.body;
if (body.startsWith(prefix)) {
body = body.substring(prefix.length);
}
// ============>
var data = json.decode(body);
var rest = data["data"] as List;
}
I am writing an application to connect to Proxmox in Flutter, and I need to get the various Authentication Realms. The issue I have had is that most servers are using a self-signed SSL certificate and the http import does not support that. This has forced me to use the dart:io package and its HttpClient. However using this method does not return any results, the List is null.
D/ ( 9335): HostConnection::get() New Host Connection established 0xe047c540, tid 9354
D/EGL_emulation( 9335): eglMakeCurrent: 0xe76a7ac0: ver 3 0 (tinfo 0xccd07000)
I/flutter ( 9335): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 9335): The following NoSuchMethodError was thrown building FormField<dynamic>(dirty, state:
I/flutter ( 9335): FormFieldState<dynamic>#11694):
I/flutter ( 9335): The method 'map' was called on null.
I/flutter ( 9335): Receiver: null
I/flutter ( 9335): Tried calling: map<DropdownMenuItem<String>>(Closure: (AuthRealm) => DropdownMenuItem<String>)
This is my client class:
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:Proxcontrol/Client/Objects/auth_realms.dart';
class Client {
String baseUrl;
Client(String url, String port) {
baseUrl = "https://" + url + ":" + port + "/api2/json/";
}
Future<List<AuthRealm>> getAuthRealms() async {
HttpClient client = new HttpClient();
client.badCertificateCallback =((X509Certificate cert, String host, int port) => true);
var request = await client.getUrl(Uri.parse(baseUrl + "access/domains"));
var response = await request.close();
return await response.transform(Utf8Decoder()).transform(JsonDecoder()).map((json) => AuthRealm.fromJson(json)).toList();
}
}
This is my AuthRealm object class that the request is mapped to:
class AuthRealm {
final String type;
final String realm;
final String comment;
AuthRealm({this.type, this.realm, this.comment});
factory AuthRealm.fromJson(Map<String, dynamic> json) {
return AuthRealm(
type: json['type'],
realm: json['realm'],
comment: json['comment']
);
}
}
And this is where I am trying to get the Authentication Realms. It then passes them to a new page where they are displayed in a dropdownbutton. The serverAddress and serverPort fields are populated via TextFields.
final nextButton = RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24)),
onPressed: () {
Client client = new Client(serverAddress, serverPort);
client.getAuthRealms().then((values) {
realms = values;
});
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ServerAuthLoginScreen(authRealms: realms)));
},
padding: EdgeInsets.all(10),
color: Colors.indigoAccent,
child: Text('NEXT', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
);
And finally the dropdownbutton section that is populated with the Authentication Realms upon loading that screen.
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:Proxcontrol/Client/Objects/auth_realms.dart';
class ServerAuthLoginScreen extends StatefulWidget {
final List<AuthRealm> authRealms;
const ServerAuthLoginScreen({Key key, #required this.authRealms}) : super(key: key);
#override
_ServerAuthLoginScreenState createState() => _ServerAuthLoginScreenState(authRealms);
}
class _ServerAuthLoginScreenState extends State<ServerAuthLoginScreen> {
List<AuthRealm> authRealms;
_ServerAuthLoginScreenState(this.authRealms);
String serverRealm;
#override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
double screenHeight = MediaQuery.of(context).size.height;
final realmSelector = FormField(
builder: (FormFieldState state) {
return InputDecorator(
decoration: InputDecoration(
icon: const Icon(FontAwesomeIcons.server),
labelText: 'Select an Auth Realm'),
isEmpty: serverRealm == '',
child: new DropdownButtonHideUnderline(
child: new DropdownButton(
isDense: true,
items: authRealms.map((AuthRealm value) {
return new DropdownMenuItem(
value: value.realm,
child: Text(value.realm),
);
}).toList(),
onChanged: (String value) {
setState(() {
serverRealm = value;
state.didChange(value);
});
}
)
),
);
},
);
_buildVerticalLayout() {
return ListView(
shrinkWrap: true,
children: <Widget>[
Padding(
padding: EdgeInsets.only(
left: screenWidth / 12,
right: screenWidth / 12,
top: screenHeight / 30),
child: realmSelector,
),
],
);
}
return Scaffold(
appBar: AppBar(
title: Text('Server Connection Details'),
centerTitle: true),
body: _buildVerticalLayout()
);
}
}
This is what my test proxmox server gives as a result to the GET request at the defined address:
{
"data":[
{
"type":"ad",
"realm":"CELESTIALDATA"
},
{
"type":"pam",
"comment":"Linux PAM standard authentication",
"realm":"pam"
},
{
"type":"pve",
"comment":"Proxmox VE authentication server",
"realm":"pve"
}
]
}
Can someone please help me understand what is going wrong? FYI I just started working with Dart/Flutter a few days ago so I am still learning how things function here. I come from a Java/C++/Python background.
UPDATE:
I modified my client in response to Richard's comment:
Future<List<AuthRealm>> getAuthRealms() async {
HttpClient client = new HttpClient();
client.badCertificateCallback =((X509Certificate cert, String host, int port) => true);
http.IOClient ioClient = new http.IOClient(client);
final response = await ioClient.get(baseUrl + "access/domains");
print(response.body);
final data = json.decode(response.body);
List<AuthRealm> realms = data.map((j) => AuthRealm.fromJson(j)).toList();
return realms;
}
However I am still getting an error and everything I am seeing just is not working.
I/flutter (12950): {"data":[{"type":"ad","realm":"CELESTIALDATA"},{"type":"pve","comment":"Proxmox VE authentication server","realm":"pve"},{"realm":"pam","comment":"Linux PAM standard authentication","type":"pam"}]}
E/flutter (12950): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: type '(dynamic) => AuthRealm' is not a subtype of type '(String, dynamic) => MapEntry<dynamic, dynamic>' of 'transform'
E/flutter (12950): #0 Client.getAuthRealms (package:Proxcontrol/Client/client.dart:70:35)
E/flutter (12950): <asynchronous suspension>
data is a Map, so you need to access the element in that map that's the list of realms. Use data['data'] to reference that list.
To convert that list of decoded json bits (List<Map<String, dynamic>>) to a list of AuthRealm use .map<AuthRealm>((j) => [something that constructs an AuthRealm]).toList()
This should work:
final data = json.decode(response.body);
List<AuthRealm> realms = data['data'].map<AuthRealm>((j) => AuthRealm.fromJson(j)).toList();
May be you should use setState like this
client.getAuthRealms().then((values) {
setState((){
realms = values;
});
});
in your code
final nextButton = RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24)),
onPressed: () {
Client client = new Client(serverAddress, serverPort);
client.getAuthRealms().then((values) {
setState(() {
realms = values;
});
});
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ServerAuthLoginScreen(authRealms: realms)));
},
padding: EdgeInsets.all(10),
color: Colors.indigoAccent,
child: Text('NEXT', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
);