Android Studio API response - flutter

I basically have everything functioning following this tutorial on how to implement a API in flutter: https://docs.flutter.dev/cookbook/networking/fetch-data. I followed the tutorial but i get an error message "Failed to load Album". My understanding of this is that the server didn't respond with a 200 ok repsonse, but im not sure. I don't know how what the problem is and how i can get it to display the information. The API im using is a car registry, where you can type in a numberplate and get all the details for a vehicle.
Future<Album> fetchAlbum() async {
final response = await http
.get(Uri.parse('http://api.nrpla.de/Cz33849?api_token=JjCYzJA0B5FQPPjlWeyUqN3KSuaErwMyrryuQCmX7R6epHagtINaMjxfwaTGGyrl'),
headers: {
});
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return Album.fromJson(jsonDecode(response.body));
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
class Album {
final String registration;
final String type;
final String brand;
final String model;
final String version;
final String fuel_type;
final String registration_status;
final int engine_power;
final String doors;
final String leasing_period_start;
final String leasing_period_end;
final String color;
final String body_type;
Album({
required this.registration,
required this.type,
required this.brand,
required this.model,
required this.version,
required this.fuel_type,
required this.registration_status,
required this.engine_power,
required this.doors,
required this.leasing_period_start,
required this.leasing_period_end,
required this.color,
required this.body_type,
});
factory Album.fromJson(Map<String, dynamic> json) {
return Album(
registration: json['registration'],
type: json['type'],
brand: json['brand'],
model: json['model'],
version: json['version'],
fuel_type: json['fuel_type'],
registration_status: json['registration_status'],
engine_power: json['engine_power'],
doors: json['doors'],
leasing_period_start: json['leasing_period_start'],
leasing_period_end: json['leasing_period_end'],
color: json['color'],
body_type: json['body_type'],
);
}
}
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late Future<Album> futureAlbum;
#override
void initState() {
super.initState();
futureAlbum = fetchAlbum();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetch Data Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: const Text('Fetch Data Example'),
),
body: Center(
child: FutureBuilder<Album>(
future: futureAlbum,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!.registration);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
// By default, show a loading spinner.
return const CircularProgressIndicator();
},
),
),
),
);
}
}

You have consumed your monthly limit that's why you are not getting data from the API status code is 429

Related

How to do HTTP GET on an API link that contains nested array in Dart/Flutter?

I am trying to create an app that shows the current data in my web server using the Flutter plugin. I want to access the details of my web server using HTTP GET.
I followed this guide (https://docs.flutter.dev/cookbook/networking/fetch-data) and used the code as well but I can't make it work on my HTTP GET link since it has nested parameters.
Here is the code from the guide:
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<Album> fetchAlbum() async {
final response = await http
.get(Uri.parse('https://jsonplaceholder.typicode.com/albums/1'));
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return Album.fromJson(jsonDecode(response.body));
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
class Album {
final int userId;
final int id;
final String title;
const Album({
required this.userId,
required this.id,
required this.title,
});
factory Album.fromJson(Map<String, dynamic> json) {
return Album(
userId: json['userId'],
id: json['id'],
title: json['title'],
);
}
}
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({super.key});
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late Future<Album> futureAlbum;
#override
void initState() {
super.initState();
futureAlbum = fetchAlbum();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetch Data Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: const Text('Fetch Data Example'),
),
body: Center(
child: FutureBuilder<Album>(
future: futureAlbum,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!.title);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
// By default, show a loading spinner.
return const CircularProgressIndicator();
},
),
),
),
);
}
}
Here is my link by the way: https://api.thingspeak.com/channels/1864145/fields/1.json?results=1
and this is the array it contains
{
"channel":{
"id":1864145,
"name":"channel name",
"description":"description",
"latitude":"0.0",
"longitude":"0.0",
"field1":"first field",
"field2":"second field",
"field3":"third field",
"field4":"fourth field",
"created_at":"2022-09-18T11:53:33Z",
"updated_at":"2022-09-18T12:26:54Z",
"last_entry_id":10742
},
"feeds":[
{"created_at":"2022-12-27T05:34:12Z",
"entry_id":10741,
"field1":"111",
"field2":"4",
"field3":"28",
"field4":"61"
}
]
}
///edit
For those confused, I don't have a code yet since I have no idea how to do it but I tried to replace the variables based on our own parameters and it did not work so I thought there is a different way/code for the nested array parameters.

Flutter http.get is not responding

I used exactly same code from Flutter Documentation to fetch data from internet.
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<Album> fetchAlbum() async {
final response = await http
.get(Uri.parse('https://jsonplaceholder.typicode.com/albums/1'));
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return Album.fromJson(jsonDecode(response.body));
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
class Album {
final int userId;
final int id;
final String title;
const Album({
required this.userId,
required this.id,
required this.title,
});
factory Album.fromJson(Map<String, dynamic> json) {
return Album(
userId: json['userId'],
id: json['id'],
title: json['title'],
);
}
}
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({super.key});
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late Future<Album> futureAlbum;
#override
void initState() {
super.initState();
futureAlbum = fetchAlbum();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetch Data Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: const Text('Fetch Data Example'),
),
body: Center(
child: FutureBuilder<Album>(
future: futureAlbum,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!.title);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
// By default, show a loading spinner.
return const CircularProgressIndicator();
},
),
),
),
);
}
}
It should display data with text widget after getting data, but http.get is not returning and it just keeps showing CircularProgressIndicator like:
I'm using Windows 10, Flutter 3.7.0 stable channel, Dart 2.19.0, http 0.13.5 version. How to fix this?
This could be because you haven't added the interne permissions in you android manifest
<manifest...
...
<uses-permission android:name="android.permission.INTERNET"/>
....
/manifest>

UI Not updating on bloc state change

I am new in using bloc library with freezed package. I have a scenario where a list of objects is coming from API is displayed. Now the list tile has a Marked as Fav button and clicking upon it a event is trigged and fav bool is toggled and state is emitted.
The Issue :
The value of the object is changed but the UI is not updated accordingly.
Main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_bloc_update/bloc/fakeapi_bloc.dart';
void main() {
runApp(
BlocProvider(
create: (context) => FakeapiBloc(),
child: const MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const Scaffold(
body: SafeArea(child: MyHomePage()),
),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
context.read<FakeapiBloc>().add(const FakeapiEvent.loadData());
super.initState();
}
#override
Widget build(BuildContext context) {
return BlocBuilder<FakeapiBloc, FakeapiState>(
builder: (context, state) {
return state.map(
inital: (_) => const Center(
child: CircularProgressIndicator(),
),
loading: (_) => const Center(
child: CircularProgressIndicator(),
),
loaded: (state) {
return ListView.builder(itemBuilder: (ctx, pos) {
return ListTile(
title: Text(state.posts[pos].title),
trailing: IconButton(
onPressed: () {
context
.read<FakeapiBloc>()
.add(FakeapiEvent.markedFav(pos: pos));
},
icon: Icon(state.posts[pos].isFav
? Icons.favorite
: Icons.favorite_border_outlined),
),
);
});
},
error: (_) => const Center(
child: CircularProgressIndicator(),
),
);
},
);
}
}
Post.dart
import 'dart:convert';
List<Post> postFromJson(String str) =>
List<Post>.from(json.decode(str).map((x) => Post.fromJson(x)));
String postToJson(List<Post> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Post {
Post({
required this.userId,
required this.id,
required this.title,
required this.body,
});
final int userId;
final int id;
final String title;
final String body;
bool isFav = false;
factory Post.fromJson(Map<String, dynamic> json) => Post(
userId: json["userId"],
id: json["id"],
title: json["title"],
body: json["body"],
);
Map<String, dynamic> toJson() => {
"userId": userId,
"id": id,
"title": title,
"body": body,
};
}
bloc.dart
import 'package:bloc/bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:freezed_bloc_update/post.dart';
import 'package:http/http.dart' as http;
part 'fakeapi_event.dart';
part 'fakeapi_state.dart';
part 'fakeapi_bloc.freezed.dart';
class FakeapiBloc extends Bloc<FakeapiEvent, FakeapiState> {
FakeapiBloc() : super(const FakeapiState.inital()) {
on<LoadData>(
(event, emit) async {
try {
emit(const FakeapiState.loading());
Uri uri = Uri.parse('https://jsonplaceholder.typicode.com/posts');
final response = await http.get(uri);
if (response.statusCode == 200) {
emit(FakeapiState.loaded(posts: postFromJson(response.body)));
} else {
emit(const FakeapiState.error(errorMessage: 'Api Call Failed'));
}
} catch (err) {
emit(const FakeapiState.error(errorMessage: 'Api Call Failed'));
}
},
);
on<MarkedFav>((event, emit) {
final previousState = state as Loaded;
previousState.posts[event.pos].isFav =
!previousState.posts[event.pos].isFav;
emit(FakeapiState.loaded(posts: [...previousState.posts]));
});
}
}
events.dart
part of 'fakeapi_bloc.dart';
#freezed
class FakeapiEvent with _$FakeapiEvent {
const factory FakeapiEvent.loadData() = LoadData;
const factory FakeapiEvent.markedFav({required int pos}) = MarkedFav;
}
states.dart
part of 'fakeapi_bloc.dart';
#freezed
class FakeapiState with _$FakeapiState {
const factory FakeapiState.inital() = Initial;
const factory FakeapiState.loading() = Loading;
const factory FakeapiState.loaded({required List<Post> posts}) = Loaded;
const factory FakeapiState.error({required String errorMessage}) = Error;
}
One solution which I did was keeping a bool variable(outside of model class) in state itself and clicking upon the fav toggling the bool value. Which is retriggering the UI update.
your Post class should be converted to a freezed class

API calls in flutter

I'm new to flutter and im trying to design an application that pulls information via a car numberplate. I have followed this tutorial regarding the API: https://docs.flutter.dev/cookbook/networking/fetch-data. For the API i need to specify the numberplate which i have used this tutorial where its saved text from the textfield: https://docs.flutter.dev/cookbook/forms/retrieve-input. I can't seem to figure out how to get text from the textfield and then make the API call.
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:async';
import 'dart:convert';
void main() => runApp(const MyApp());
Future<Album> fetchAlbum() async {
final response = await http
.get(Uri.parse('https://v1.motorapi.dk/vehicles/'),
headers: {"X-AUTH-TOKEN": "rfrzsucnc7eo3m5hcmq6ljdzda1lz793"});
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return Album.fromJson(jsonDecode(response.body));
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
//headers: {"X-AUTH-TOKEN": "rfrzsucnc7eo3m5hcmq6ljdzda1lz793"}
class Album {
final String registration_number;
final String status;
final String type;
final String use;
final String first_registration;
final String vin;
final int doors;
final String make;
final String model;
final String variant;
final String model_type;
final String color;
final String chasis_type;
final String engine_power;
final String fuel_type;
final String RegistreringssynToldsyn;
final String date;
final String result;
Album({
required this.registration_number,
required this.status,
required this.type,
required this.use,
required this.first_registration,
required this.vin,
required this.doors,
required this.make,
required this.model,
required this.variant,
required this.model_type,
required this.color,
required this.chasis_type,
required this.engine_power,
required this.fuel_type,
required this.RegistreringssynToldsyn,
required this.date,
required this.result,
});
factory Album.fromJson(Map<String, dynamic> json) {
return Album(
registration_number: json['registration_number'],
status: json['status'],
type: json['type'],
use: json['use'],
first_registration: json['first_registration'],
vin: json['vin'],
doors: json['doors'],
make: json['make'],
model: json['model'],
variant: json['variant'],
model_type: json['model_type'],
color: json['color'],
chasis_type: json['chasis_type'],
engine_power: json['engine_power'],
fuel_type: json['fuel_type'],
RegistreringssynToldsyn: json['RegistreringssynToldsyn'],
date: json['date'],
result: json['result'],
);
}
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Retrieve Text Input',
home: MyCustomForm(),
);
}
}
// Define a custom Form widget.
class MyCustomForm extends StatefulWidget {
const MyCustomForm({Key? key}) : super(key: key);
#override
_MyCustomFormState createState() => _MyCustomFormState();
}
// Define a corresponding State class.
// This class holds the data related to the Form.
class _MyCustomFormState extends State<MyCustomForm> {
// Create a text controller and use it to retrieve the current value
// of the TextField.
final myController = TextEditingController();
#override
void dispose() {
// Clean up the controller when the widget is disposed.
myController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Retrieve Text Input'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: TextField(
controller: myController,
),
),
floatingActionButton: FloatingActionButton(
// When the user presses the button, show an alert dialog containing
// the text that the user has entered into the text field.
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
// Retrieve the text the that user has entered by using the
// TextEditingController.
content: Text(myController.text),
);
},
);
},
tooltip: 'Show me the value!',
child: const Icon(Icons.text_fields),
),
);
}
}
change your code for this
// Define a corresponding State class.
// This class holds the data related to the Form.
class _MyCustomFormState extends State<MyCustomForm> {
// Create a text controller and use it to retrieve the current value
// of the TextField.
TextEditingController myController ;
#override
void dispose() {
// Clean up the controller when the widget is disposed.
myController.dispose();
super.dispose();
}
#override
void initState() {
super.initState();
myController=TextEditingController();
futureAlbum = fetchAlbum();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Retrieve Text Input'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: TextField(
controller: myController,
),
),
floatingActionButton: FloatingActionButton(
// When the user presses the button, show an alert dialog containing
// the text that the user has entered into the text field.
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
// Retrieve the text the that user has entered by using the
// TextEditingController.
content: Text(myController.text),
);
},
);
},
tooltip: 'Show me the value!',
child: const Icon(Icons.text_fields),
),
);
}
You miss this method
#override
void initState() {
super.initState();
futureAlbum = fetchAlbum();
}

How to Pass parameters in url. in flutter

I want to pass some parameters in flutter url
here is example:
parameters are source , destination , type, fare.
url is http://localhost:9000/api/bmrc/fare/source/destination/fare/type
url need to send http://localhost:9000/api/bmrc/fare/1/17/2/SJT
(workinng in postman/thunderclient)
I tried after passing these parameters in body but its not worked for me
They are Path Parameters, not body JSON.
You can call your API like this:
callAPI(int source,int destination,int fare,String type){
String _url= "http://localhost:9000/api/bmrc/fare/${source}/${destination}/${fare}/${type}";
... //call your API with _url
}
You can change the param types as you like
its a POST Call:
To get data from from your url, try this.
Here is the sample Example:
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
MyApp({Key key}) : super(key: key);
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Future<Post> post;
#override
void initState() {
super.initState();
post = fetchPost();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter REST API Example',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: Scaffold(
appBar: AppBar(
title: Text('Flutter REST API Example'),
),
body: Center(
child: FutureBuilder<Post>(
future: post,
builder: (context, abc) {
if (abc.hasData) {
return Text(abc.data.title);
} else if (abc.hasError) {
return Text("${abc.error}");
}
// By default, it show a loading spinner.
return CircularProgressIndicator();
},
),
),
),
);
}
}
Future<Post> fetchPost() async {
final response = await http.get('Give your JSON file web link.');
if (response.statusCode == 200) {
// If the call to the server was successful (returns OK), parse the JSON.
return Post.fromJson(json.decode(response.body));
} else {
// If that call was not successful (response was unexpected), it throw an error.
throw Exception('Failed to load post');
}
}
class Post {
final int userId;
final int id;
final String title;
final String description;
Post({this.userId, this.id, this.title, this. description});
factory Post.fromJson(Map<String, dynamic> json) {
return Post(
userId: json['userId'],
id: json['id'],
title: json['title'],
description: json[' description'],
);
}
}