Skip to content

Instantly share code, notes, and snippets.

@ansisec
Last active December 19, 2023 13:52
Show Gist options
  • Save ansisec/7443070c2dd2f53a9ec40248cf0c88af to your computer and use it in GitHub Desktop.
Save ansisec/7443070c2dd2f53a9ec40248cf0c88af to your computer and use it in GitHub Desktop.
P11 - Flutter 2
Código auxiliar para a aula 2 de Flutter
//Add the following method
Future<String> _fetchAnAsyncString() async {
await Future.delayed(const Duration(seconds: 5));
return Future.value('Hello world, from an aysnc call!');
}
//Inside the build method:
FutureBuilder<String>(
future: _fetchAnAsyncString(),
builder: (
BuildContext context, AsyncSnapshot<String> snapshot
) {
if (snapshot.hasData) {
return Text(snapshot.data!);
} else if (snapshot.hasError) {
return const Text('Oops, something happened');
} else {
return const CircularProgressIndicator();
}
},
),
static const String _catFactsUrl = 'https://catfact.ninja/facts';
//inside the build method:
FutureBuilder<http.Response>(
future: http.get(Uri.parse(_catFactsUrl)),
builder: (
BuildContext context,AsyncSnapshot<http.Response> snapshot
) {
if (snapshot.hasData) {
return Expanded(
child: SingleChildScrollView(
child: Text(snapshot.data!.body)
)
);
} else if (snapshot.hasError) {
return const Text('Oops, something happened');
} else {
return const CircularProgressIndicator();
}
},
),
//outside any class:
class CatFact {
CatFact.fromJson(Map<String, dynamic> json)
: fact = json['fact'],
length = json['length'];
final String fact;
final int length;
}
//inside the state:
List<CatFact>? _catFacts;
bool _fetchingData = false;
Future<void> _fetchCatFacts() async {
try {
setState(() => _fetchingData = true);
http.Response response = await http.get(Uri.parse(_catFactsUrl));
if (response.statusCode == HttpStatus.ok) { //import 'dart:io';
debugPrint(response.body);
final Map<String, dynamic> decodedData = json.decode(response.body);
setState(() => _catFacts = (decodedData['data'] as List).map((fact) => CatFact.fromJson(fact)).toList());
}
} catch (ex) {
debugPrint('Something went wrong: $ex');
} finally {
setState(() => _fetchingData = false);
}
}
//inside the build method:
ElevatedButton(
onPressed: _fetchCatFacts,
child: const Text('Fetch cat facts'),
),
if (_fetchingData) const CircularProgressIndicator(),
if (!_fetchingData && _catFacts != null && _catFacts!.isNotEmpty)
Expanded(
child: ListView.separated(
itemCount: _catFacts!.length,
separatorBuilder: (_, __) => const Divider(thickness: 2.0),
itemBuilder: (BuildContext context, int index) => ListTile(
title: Text('Cat fact #$index'),
subtitle: Text(_catFacts![index].fact),
),
),
)
// Create an images directory in the project
// Place an image of your choice in the directory
// .../<flutter_prj_path>/images/xpto.jpg
//Add (at the end of the pubspec.yaml file; be careful with the indentation):
flutter:
...
assets:
- images/xpto.jpg
// before the first text in the Stateful Widget, add:
SizedBox(height:200, child: Image.asset('images/xpto.jpg'))
static const String _ipc_logo = 'https://wayf.ipc.pt/IPCds/images/logo_ipc2.png';
//after or replacing the previous image:
SizedBox(height:50, child: Image.network(_ipc_logo)),
//Comment the _incrementCounter method and add:
int _inc=1;
void changeInc(int inc) { setState(() {_inc = inc;}); }
void _incrementCounter() { setState(() {_counter+=_inc; }); }
//insert in the build method:
TextField(
decoration: const InputDecoration(
labelText: 'Increment:',
hintText: 'Value to increment',
),
onChanged: (value) => changeInc(int.tryParse(value) ?? 1),
),
//first: include the shared_preferences plugin
@override
void initState() {
super.initState();
initCounter();
}
Future<void> initCounter() async {
var prefs = await SharedPreferences.getInstance();
setState (() { _counter = prefs.getInt ('counter') ?? 1; } );
}
void _incrementCounter() async {
setState (() { _counter++; } );
var prefs = await SharedPreferences.getInstance();
await prefs.setInt('counter', _counter);
}
//first: include the location plugin
//Change the kotlin version in the project build.gradle: ext.kotlin_version = '1.9.0'
//include permissions in the manifest file
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
//include in the state class:
Location location = Location();
bool _serviceEnabled = false;
PermissionStatus _permissionGranted = PermissionStatus.denied;
LocationData _locationData = LocationData.fromMap({
"latitude": 40.192639,
"longitude": -8.411899,
});
void getLocation() async {
_serviceEnabled = await location.serviceEnabled();
if (!_serviceEnabled) {
_serviceEnabled = await location.requestService();
if (!_serviceEnabled) {
return;
}
}
_permissionGranted = await location.hasPermission();
if (_permissionGranted == PermissionStatus.denied) {
_permissionGranted = await location.requestPermission();
if (_permissionGranted != PermissionStatus.granted) {
return;
}
}
_locationData = await location.getLocation();
setState(() { });
}
//include in the build method:
Text('Latitude: ${_locationData.latitude}; Longitude: ${_locationData.longitude}'),
ElevatedButton(onPressed: getLocation, child: const Text("Refresh")),
// automatic updates
StreamSubscription<LocationData>? _locationSubscription;
void startLocationUpdates() {
_locationSubscription=location.onLocationChanged.listen((LocationData currentLocation) {
setState(() {_locationData = currentLocation;});
});
}
void stopLocationUpdates() {
_locationSubscription?.cancel();
_locationSubscription=null;
}
//include in the build method:
ElevatedButton(onPressed: startLocationUpdates, child: const Text("Start")),
ElevatedButton(onPressed: stopLocationUpdates, child: const Text("Stop")),
StreamBuilder(
stream: location.onLocationChanged,
builder: (context,snapshot) {
if (snapshot.hasData) {
return Text(
'LatitudeB: ${snapshot.data!.latitude}; '
'LongitudeB: ${snapshot.data!.longitude}'
);
}
return const CircularProgressIndicator();
}
),
//pubspec.yaml
firebase_core: any
cloud_firestore: any
-- *** --
// main.dart
//....
import 'package:firebase_core/firebase_core.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'firebase_options.dart';
void initFirebase() async {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
}
void main() {
// Ensure that Flutter is initialized before Firebase
WidgetsFlutterBinding.ensureInitialized();
initFirebase();
runApp(const MyApp());
}
//...
-- *** --
String? _error;
void addFirebase() async {
var db = FirebaseFirestore.instance;
var document = db.collection('MyColl').doc("MyDocAMOV");
await document.set({
'subject': 'Mobile Architectures',
'nrStudents': 0}
).onError(
(error, stackTrace) {
setState(() {_error = error.toString();});
});
setState(() {
_error = null;
});
}
void delFirebase() async {
var db = FirebaseFirestore.instance;
var document = db.collection('MyColl').doc("MyDocAMOV");
await document.delete().onError(
(error, stackTrace) {
setState(() {_error = error.toString();});
debugPrint('Error!!!');
});
setState(() {
_error = null;
});
}
void updateFirebase() async {
var db = FirebaseFirestore.instance;
var document = db.collection('MyColl').doc("MyDocAMOV");
var data = await document.get(const GetOptions(source: Source.server));
if (data.exists) {
var nrStudents = data['nrStudents'] + 1;
document.update({'nrStudents': nrStudents}).then(
(res) => setState(() { _error = null; }),
onError: (e) => setState(() { _error = e.toString();})
);
} else {
setState(() { _error = "Document doesn't exist";});
}
}
void listDocuments() async {
var db = FirebaseFirestore.instance;
var collection = await db.collection('MyColl').get();
for(var doc in collection.docs) {
debugPrint("Doc: ${doc.id}"); //doc.data()...
}
}
-- *** --
//inside the build method:
if (_error != null) Text("Error: $_error"),
ElevatedButton(
onPressed: addFirebase,
child: const Text('Add document'),
),
ElevatedButton(
onPressed: delFirebase,
child: const Text('Del document'),
),
ElevatedButton(
onPressed: updateFirebase,
child: const Text('Update document'),
),
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment