As I mentioned at the title, I got this error:
Exception caught by widgets library
Closure call with mismatched arguments: function '[]'
Receiver: Closure: () => Map<String, dynamic> from Function 'data':.
Tried calling: []("imageURL")
Found: []() => Map<String, dynamic>
I have been trying to use it to get data from firestore and show it on my app page. But I can't get the data from collection, especially for images. I referenced this tutorial from youtube. Even though I've done everything same but I couldn't handle it. Maybe bc of version. I'd be glad if you help me.
class _HomeState extends State<Home> {
PostService postService = new PostService();
Stream postStream;
//Stream postsStream;
Widget postsList() {
return SingleChildScrollView(
child: postStream != null
? Column(
children: <Widget>[
StreamBuilder(
//stream: postStream,
stream: postStream,
builder: (context, snapshot)
{
if(snapshot.data == null) return CircularProgressIndicator();
return ListView.builder(
padding: EdgeInsets.symmetric(horizontal:16.0),
itemCount: snapshot.data.docs.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return PostTile(
imgUrl: snapshot.data.docs[index].data['imageURL'],
title: snapshot.data.docs[index].data['postTitle'],
desc: snapshot.data.docs[index].data['postDesc'],
city: snapshot.data.docs[index].data['cityName'],
);
});
}),
],
): Container(
alignment: Alignment.center,
child: CircularProgressIndicator(),
),
);
}
#override
void initState() {
postService.getPostData().then((result) {
setState(() {
postStream = result;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text('Ana Sayfa'),
backgroundColor: Colors.amber,
elevation: 0.0,
actions: <Widget>[
FlatButton.icon(
icon: Icon(Icons.group_rounded),
label: Text(''),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => KullaniciSayfasi()));
},
),
],
),
body: postsList(),
floatingActionButton: Container(
padding: EdgeInsets.symmetric(vertical: 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FloatingActionButton(
onPressed: () {
//Ekleme butonuna basıldığında
Navigator.push(context,
MaterialPageRoute(builder: (context) => CreatePost()));
},
child: Icon(Icons.add),
)
],
),
),
);
}
}
Code for post service
import 'package:cloud_firestore/cloud_firestore.dart';
class PostService{
Future<void> addData(postData) async{
FirebaseFirestore.instance.collection("posts").add(postData).catchError((e){
print(e);
});
}
getPostData() async{
return await FirebaseFirestore.instance.collection("posts").snapshots();
}
}
There was a breaking change on firebase plugins and many things have changed. E.g i see you're doing snapshot.data.docs[index].data['imageURL'] this has been changed to snapshot.data.docs[index].data()['imageURL']. Kindly check the docs for the updated API refrences
Related
I have made an to do list with firebase. but when i click to create a new to do, i can't see anything apear on my page but in firebase it does show the string.
How can i fix this
(this is in flutter)
logcat:
2022-10-19 15:24:50.758 23369-23584 flutter com.example.voorbeeld I apen created
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class video_info extends StatefulWidget {
#override
_video_infoState createState() => _video_infoState();
}
class _video_infoState extends State<video_info> {
String todoTitle = "";
createTodos() {
DocumentReference documentReference =
FirebaseFirestore.instance.collection("MyTodos").doc(todoTitle);
//Map
Map<String, String> todos = {"todoTitle": todoTitle};
documentReference.set(todos).whenComplete(() {
print("$todoTitle created");
});
}
deleteTodos(item) {
DocumentReference documentReference =
FirebaseFirestore.instance.collection("MyTodos").doc(item);
documentReference.delete().whenComplete(() {
print("$item deleted");
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("mytodos"),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8)),
title: Text("Add Todolist"),
content: TextField(
onChanged: (String value) {
todoTitle = value;
},
),
actions: <Widget>[
TextButton(
onPressed:() {
createTodos();
Navigator.of(context).pop();
},
child: Text("Add"))
],
);
});
},
child: Icon(
Icons.add,
color: Colors.white,
),
),
body: StreamBuilder(
stream: FirebaseFirestore.instance.collection("Mytodos").snapshots(),
builder: (context, snapshots) {
if (snapshots.hasData) {
return ListView.builder(
shrinkWrap: true,
itemCount: snapshots.data?.docs.length,
itemBuilder: (context, index) {
DocumentSnapshot documentSnapshot =
snapshots.data!.docs[index];
return Dismissible(
onDismissed: (direction) {
deleteTodos(documentSnapshot["todoTitle"]);
},
key: Key(documentSnapshot["todoTitle"]),
child: Card(
elevation: 4,
margin: EdgeInsets.all(8),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8)),
child: ListTile(
title: Text(documentSnapshot["todoTitle"]),
trailing: IconButton(
icon: Icon(
Icons.delete,
color: Colors.red,
),
onPressed: () {
deleteTodos(documentSnapshot["todoTitle"]);
}),
),
));
});
} else {
return Align(
alignment: FractionalOffset.bottomCenter,
child: CircularProgressIndicator(),
);
}
}),
);
}}
also does anyone know a link to an tuturial where they explain how i can link the database to a user login.
You're using another collection.
You are adding your todo to this collection:
FirebaseFirestore.instance.collection("MyTodos")
But in your StreamBuilder you use the collection "Mytodos":
stream: FirebaseFirestore.instance.collection("Mytodos").snapshots(),
Try creating a stream variable on state class
late final myStream = FirebaseFirestore.instance.collection("MyTodos").snapshots();
#override
Widget build(BuildContext context) {
....
body: StreamBuilder(
stream: myStream
I don't know what happened, but I tried to fix this by making it nullable, but it didn't work.
I wanted to view elements from the database, therefore i put them in "for" loop..
but it still showing me exception _TypeError (type 'Null' is not a subtype of type 'String')
So what should I do to fix this?
This is a screenshot of the exception:
enter image description here
And this is my code:
`import 'pac`kage:blackboard/view/Teacher/Addcourse1.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:blackboard/constraints/textstyle.dart';
import 'package:flutter/material.dart';
import 'package:blackboard/setting/colors.dart';
class CoursesT extends StatefulWidget {
const CoursesT({Key? key}) : super(key: key);
#override
State<CoursesT> createState() => _CoursesTState();
}
class _CoursesTState extends State<CoursesT> {
// Getting Student all Records
final Stream<QuerySnapshot>? studentRecords =
FirebaseFirestore.instance.collection('CourseStudent').snapshots();
// For Deleting Users
CollectionReference? delUser =
FirebaseFirestore.instance.collection('CourseStudent');
Future<void> _delete(id) {
return delUser!
.doc(id)
.delete()
.then((value) => print('User Deleted'))
.catchError((_) => print('Something Error In Deleted User'));
}
#override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: studentRecords,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
print('Something Wrong in HomePage');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
}
// Storing Data
final List? firebaseData = [];
snapshot.data?.docs.map((DocumentSnapshot documentSnapshot) {
Map store = documentSnapshot.data() as Map<String, dynamic>;
firebaseData!.add(store);
store['id'] = documentSnapshot.id;
}).toList();
return Scaffold(
appBar: AppBar(
backgroundColor: BBColors.primary6,
title: Text("Your Courses"),
leading: Icon(Icons.menu, color: Colors.white),
actions: [
Icon(
Icons.search,
),
SizedBox(
width: 20,
),
],
),
body: Container(
margin: const EdgeInsets.all(8),
child: SingleChildScrollView(
child: ListView(
shrinkWrap: true,
children: [
for (var i = 0; i < firebaseData!.length; i++) ...[
Card(
elevation: 4.0,
child: Column(
children: [
ListTile(
title: Text(
firebaseData[i]['Course Title'],
),
subtitle: Text(
firebaseData[i]['Course Group'],
),
trailing: IconButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
const AddCourse1(),
),
);
},
icon: const Icon(
Icons.add,
color: BBColors.bg1,
),
),
),
Container(
padding: EdgeInsets.all(16.0),
alignment: Alignment.centerLeft,
child: Text(
firebaseData[i]['Course Description'],
),
),
ButtonBar(
children: [
// IconButton(
// onPressed: () {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => EditPage(
// docID: firebaseData[i]['id'],
// ),
// ),
// );
// },
// icon: const Icon(
// Icons.edit,
// color: Colors.orange,
// ),
// ),
IconButton(
onPressed: () {
_delete(firebaseData[i]['id']);
//print(firebaseData);
},
icon: const Icon(
Icons.delete,
color: Colors.red,
),
),
],
)
],
)),
], //this is loop
],
),
),
),
);
});
}
}
just check wheather you are getting data from firebase in firebaseData variable and also refactor you code like this
subtitle: Text(firebaseData[i]['Course Group']??"Some Text",),
If your variable return null then it will print the hard-coded text on the right and save app from crashing.
Everything related services at any point might received as "null". I suggest making any variable depends on internet interaction, nullable. So when you use them you can have placeholder values.
For example
String? theUserNameFetchedFromInternet
// while using
Text(theUserNameFetchedFromInternet ?? "john")
This type of handling prevents lots of crash over-time & is there is why dart is null-safety.
I am trying to make a list of medicines in my mobile app. My data is in a local json file.
{
"BARKOD": 8699755640016,
"ATC KODU": "A01AA",
"ATC ADI": "Caries prophylactic agents",
"REFERANS \nE�DE�ER": "E�DE�ER",
"ESDEGERI": 2,
"ILAC ADI": "SENSORAL 250 ML SOLUSYON",
"ETKIN MADDE": "POTASYUM NITRAT + SODYUM KLORUR",
"FIRMA ADI": "DENTORAL MEDIFARMA",
"BIRIM MIKTAR": "",
"BIRIM CINSI": "",
"AMBALAJ MIKTARI": 250,
"RE�ETE": "NORMAL RE�ETE",
"KDV DAHIL PERAKENDE SATIS TL FIYATI \n1 ? =2,1166 TL": "5,69"
},
one of them is like that.
I am trying to make all of these data to appear when I click on a button. My code is like below.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:medicine_reminder/src/ui/homepage/homepage.dart';
class JsonPage extends StatefulWidget {
#override
_JsonPageState createState() => _JsonPageState();
}
class _JsonPageState extends State<JsonPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Medicine List"),
centerTitle: true,
),
body: Center(
child: FutureBuilder(
builder: (context, snapshot) {
var showData = json.decode(snapshot.data.toString());
return ListView.builder(
itemBuilder: (BuildContext context, int index) {
return ListTile(
isThreeLine: true,
title: Text(showData[index]['ILAC ADI']),
subtitle: Text(showData[index]['ETKIN MADDE']),
);
},
itemCount: showData.length,
);
},
future:
DefaultAssetBundle.of(context).loadString("assets/csvjson.json"),
),
),
floatingActionButton: Stack(
children: <Widget>[
Padding(
padding: EdgeInsets.only(right: 1),
child: Align(
heightFactor: 12.9,
alignment: Alignment.topLeft,
child: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HomePage(),
));
},
child: Icon(Icons.arrow_back),
),
),
),
],
),
);
}
}
but I can not get all the fields, I am only able to get just 2 fields 'ILAC ADI' AND 'ETKIN MADDE'.
How can I solve this?
The most efficient way to dealing with json data and rendering them is by creating models. If you are new to this QuickType can help you out with this.
Paste your json and you will get the code for the model. Next u can instantiate the model with your json data and use ListView.builder to iterate through your model and render the data.
Retroportal studio has a good video explaining this concept, take a look. I'm sure it will help you out.
Only 'ILAC ADI' and 'ETKIN MADDE' is showing on the screen because you are giving only those values in the ListTile.
Instead of a ListTile you can use a Column to show all the data.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:medicine_reminder/src/ui/homepage/homepage.dart';
class JsonPage extends StatefulWidget {
#override
_JsonPageState createState() => _JsonPageState();
}
class _JsonPageState extends State<JsonPage> {
// This List stores all the keys in the JSON
final List<String> jsonKeyList = [
'BARKOD',
'ATC KODU',
'ATC ADI',
'REFERANS \nE�DE�ER',
'ESDEGERI',
'ILAC ADI',
'ETKIN MADDE',
'FIRMA ADI',
'BIRIM MIKTAR',
'BIRIM CINSI',
'AMBALAJ MIKTARI',
'RE�ETE',
'KDV DAHIL PERAKENDE SATIS TL FIYATI \n1 ? =2,1166 TL',
];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Medicine List"),
centerTitle: true,
),
body: Center(
child: FutureBuilder(
builder: (context, snapshot) {
var showData = json.decode(snapshot.data);
print(showData.toString());
return ListView.builder(
itemBuilder: (BuildContext context, int index) {
// Used column to show all the values in the JSON
return Column(
children: jsonKeyList.map((key) {
return Text(showData[index][key].toString());
}).toList(),
);
},
itemCount: showData.length,
);
},
future:
DefaultAssetBundle.of(context).loadString("assets/csvjson.json"),
),
),
floatingActionButton: Stack(
children: <Widget>[
Padding(
padding: EdgeInsets.only(right: 1),
child: Align(
heightFactor: 12.9,
alignment: Alignment.topLeft,
child: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HomePage(),
));
},
child: Icon(Icons.arrow_back),
),
),
),
],
),
);
}
}
If you have any doubt comment it.
I am currently running into an issue with my ble project for flutter. I am using the flutter blue package by Paul DeMarco and the additional page for the app is based on "ThatProject" dust sensor from youtube. I have an Adafruit Feather 32u4 board, and I am attempting to notify the client (my flutter app) that It has a series of numbers to send, but I am not getting any output. I am able to connect to the device, and seem to properly send the service UUID and characteristic UUID, but im not sure if it is coming with proper properties.
I am using the adafruit BLE code to program the board, and I can get the values if I use adafruit's app. I am just trying to get the values on my own flutter app.
I am running into an error as follows:
E/flutter (32139): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: PlatformException(set_notification_error, could not locate CCCD descriptor for characteristic: 6e400002-b5a3-f393-e0a9-e50e24dcca9e, null, null)
Here is my code. I believe the missing CCCD is coming from this part:
import 'dart:async';
import 'dart:convert' show utf8;
import 'package:flutter/material.dart';
import 'package:flutter_blue/flutter_blue.dart';
import 'package:oscilloscope/oscilloscope.dart';
class SensorPage extends StatefulWidget {
const SensorPage({Key key, this.device}) : super(key: key);
final BluetoothDevice device;
#override
_SensorPageState createState() => _SensorPageState();
}
class _SensorPageState extends State<SensorPage> {
final String SERVICE_UUID = "6e400001-b5a3-f393-e0a9-e50e24dcca9e";
final String CHARACTERISTIC_UUID = "6e400002-b5a3-f393-e0a9-e50e24dcca9e";
bool isReady;
Stream<List<int>> stream;
List<double> traceDust = List();
#override
void initState() {
super.initState();
isReady = false;
connectToDevice();
}
connectToDevice() async {
// if (widget.device == null) {
// // _Pop();
// return;
// }
//timeout timer, watchdog timer if you will
new Timer(const Duration(seconds: 15), () {
if (!isReady) {
disconnectFromDevice();
// _Pop();
}
});
await widget.device.connect();
discoverServices();
}
disconnectFromDevice() {
if (widget.device == null) {
//_Pop();
return;
}
widget.device.disconnect();
}
discoverServices() async {
// if (widget.device == null) {
// // _Pop();
// return;
// }
BluetoothCharacteristic ss;
List<BluetoothService> services = await widget.device.discoverServices();
services.forEach((service) {
debugPrint("This Service UUID is!${service.uuid.toString()}");
if (service.uuid.toString() == SERVICE_UUID) {
service.characteristics.forEach((characteristic) {
debugPrint("This char UUID is!${characteristic.uuid.toString()}");
if (characteristic.uuid.toString() == CHARACTERISTIC_UUID) {
debugPrint("Here is !isNotifying: ${!characteristic.isNotifying}");
debugPrint("Here is characteristic.value: ${characteristic.value}");
ss = characteristic;
stream = ss.value;
setState(() {
isReady = true;
});
} //this one
});
} //this one
});
await ss.setNotifyValue(true);
stream = ss.value;
if (!isReady) {
// _Pop();
}
}
Future<bool> _onWillPop() {
return showDialog(
context: context,
builder: (context) =>
new AlertDialog(
title: Text('Are you sure?'),
content: Text('Do you want to disconnect device and go back?'),
actions: <Widget>[
new FlatButton(
onPressed: () => Navigator.of(context).pop(false),
child: new Text('No')),
new FlatButton(
onPressed: () {
disconnectFromDevice();
Navigator.of(context).pop(true);
},
child: new Text('Yes')),
],
) ??
false);
}
// _Pop() {
// Navigator.of(context).pop(true);
// }
String _dataParser(List<int> dataFromDevice) {
debugPrint("current value is-> ${utf8.decode(dataFromDevice)}");
return utf8.decode(dataFromDevice);
}
#override
Widget build(BuildContext context) {
Oscilloscope oscilloscope = Oscilloscope(
showYAxis: true,
padding: 0.0,
backgroundColor: Colors.black,
traceColor: Colors.white,
yAxisMax: 3000.0,
yAxisMin: 0.0,
dataSet: traceDust,
);
return WillPopScope(
onWillPop: _onWillPop,
child: Scaffold(
appBar: AppBar(
title: Text('Optical Dust Sensor'),
),
body: Container(
child: !isReady
? Center(
child: Text(
"Waiting...",
style: TextStyle(fontSize: 24, color: Colors.red),
),
)
: Container(
child: StreamBuilder<List<int>>(
stream: stream,
builder: (BuildContext context,
AsyncSnapshot<List<int>> snapshot) {
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
if (snapshot.connectionState ==
ConnectionState.active) {
debugPrint("snapshot.error: ${snapshot.error}.");
debugPrint("snapshot.data: ${snapshot.error}.");
debugPrint(
"snapshot.connectionState: ${snapshot.connectionState}.");
debugPrint("snapshot.hasdata?: ${snapshot.hasData}.");
var currentValue = _dataParser(snapshot.data);
traceDust.add(double.tryParse(currentValue) ?? 0);
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 1,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Current value from Sensor',
style: TextStyle(fontSize: 14)),
Text('$currentValue ug/m3',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 24))
]),
),
Expanded(
flex: 1,
child: oscilloscope,
)
],
));
} else {
return Text('Check the stream');
}
},
),
)),
),
);
}
}
// Copyright 2017, Paul DeMarco.
// All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:K9Harness/Pages/Sensor_page.dart';
import 'package:K9Harness/Bluetooth/widgets.dart';
import 'package:flutter_blue/flutter_blue.dart';
class MyBluetoothPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
color: Colors.lightBlue,
home: StreamBuilder<BluetoothState>(
stream: FlutterBlue.instance.state,
initialData: BluetoothState.unknown,
builder: (c, snapshot) {
final state = snapshot.data;
if (state == BluetoothState.on) {
return FindDevicesScreen();
}
return BluetoothOffScreen(state: state);
}),
);
}
}
class BluetoothOffScreen extends StatelessWidget {
const BluetoothOffScreen({Key key, this.state}) : super(key: key);
final BluetoothState state;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.lightBlue,
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Icon(
Icons.bluetooth_disabled,
size: 200.0,
color: Colors.white54,
),
Text(
'Bluetooth Adapter is ${state.toString().substring(15)}.',
style: Theme.of(context)
.primaryTextTheme
.subhead
.copyWith(color: Colors.white),
),
],
),
),
);
}
}
class FindDevicesScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Find Devices'),
),
body: RefreshIndicator(
onRefresh: () => FlutterBlue.instance
.startScan(
scanMode: ScanMode.balanced,
withServices: [
Guid("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")
], //FIXME check the other ways where ".startScan" is implemented
timeout: Duration(seconds: 4))
.catchError((error) {
print("error starting scan $error");
}),
child: SingleChildScrollView(
child: Column(
children: <Widget>[
StreamBuilder<List<BluetoothDevice>>(
stream: Stream.periodic(Duration(seconds: 2))
.asyncMap((_) => FlutterBlue.instance.connectedDevices),
initialData: [],
builder: (c, snapshot) => Column(
children: snapshot.data
.map((d) => ListTile(
title: Text(d.name),
subtitle: Text(d.id.toString()),
trailing: StreamBuilder<BluetoothDeviceState>(
stream: d.state,
initialData: BluetoothDeviceState.disconnected,
builder: (c, snapshot) {
if (snapshot.data ==
BluetoothDeviceState.connected) {
return RaisedButton(
child: Text('OPEN'),
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
DeviceScreen(device: d))),
);
}
return Text(snapshot.data.toString());
},
),
))
.toList(),
),
),
StreamBuilder<List<ScanResult>>(
stream: FlutterBlue.instance.scanResults,
initialData: [],
builder: (c, snapshot) => Column(
children: snapshot.data
.map(
(r) => ScanResultTile(
result: r,
onTap: () => Navigator.of(context)
.push(MaterialPageRoute(builder: (context) {
r.device.connect();
return SensorPage(device: r.device);
})),
),
)
.toList(),
),
),
],
),
),
),
floatingActionButton: StreamBuilder<bool>(
stream: FlutterBlue.instance.isScanning,
initialData: false,
builder: (c, snapshot) {
if (snapshot.data) {
return FloatingActionButton(
child: Icon(Icons.stop),
onPressed: () => FlutterBlue.instance.stopScan(),
backgroundColor: Colors.red,
);
} else {
return FloatingActionButton(
child: Icon(Icons.search),
onPressed: () => FlutterBlue.instance
.startScan(
scanMode: ScanMode.balanced,
withServices: [
Guid("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")
], //FIXME check the other ways where ".startScan" is implemented
timeout: Duration(seconds: 4))
.catchError((error) {
print("error starting scan $error");
}));
}
},
),
);
}
}
class DeviceScreen extends StatelessWidget {
const DeviceScreen({Key key, this.device}) : super(key: key);
final BluetoothDevice device;
List<Widget> _buildServiceTiles(List<BluetoothService> services) {
return services
.map(
(s) => ServiceTile(
service: s,
characteristicTiles: s.characteristics
.map(
(c) => CharacteristicTile(
characteristic: c,
onReadPressed: () => c.read(),
onWritePressed: () => c.write([13, 24]),
onNotificationPressed: () =>
c.setNotifyValue(!c.isNotifying),
descriptorTiles: c.descriptors
.map(
(d) => DescriptorTile(
descriptor: d,
onReadPressed: () => d.read(),
onWritePressed: () => d.write([11, 12]),
),
)
.toList(),
),
)
.toList(),
),
)
.toList();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(device.name),
actions: <Widget>[
StreamBuilder<BluetoothDeviceState>(
stream: device.state,
initialData: BluetoothDeviceState.connecting,
builder: (c, snapshot) {
VoidCallback onPressed;
String text;
switch (snapshot.data) {
case BluetoothDeviceState.connected:
onPressed = () => device.disconnect();
text = 'DISCONNECT';
break;
case BluetoothDeviceState.disconnected:
onPressed = () => device.connect();
text = 'CONNECT';
break;
default:
onPressed = null;
text = snapshot.data.toString().substring(21).toUpperCase();
break;
}
return FlatButton(
onPressed: onPressed,
child: Text(
text,
style: Theme.of(context)
.primaryTextTheme
.button
.copyWith(color: Colors.white),
));
},
)
],
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
StreamBuilder<BluetoothDeviceState>(
stream: device.state,
initialData: BluetoothDeviceState.connecting,
builder: (c, snapshot) => ListTile(
leading: (snapshot.data == BluetoothDeviceState.connected)
? Icon(Icons.bluetooth_connected)
: Icon(Icons.bluetooth_disabled),
title: Text(
'Device is ${snapshot.data.toString().split('.')[1]}.'),
subtitle: Text('${device.id}'),
trailing: StreamBuilder<bool>(
stream: device.isDiscoveringServices,
initialData: false,
builder: (c, snapshot) => IndexedStack(
index: snapshot.data ? 1 : 0,
children: <Widget>[
IconButton(
icon: Icon(Icons.refresh),
onPressed: () => device.discoverServices(),
),
IconButton(
icon: SizedBox(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation(Colors.grey),
),
width: 18.0,
height: 18.0,
),
onPressed: null,
)
],
),
),
),
),
StreamBuilder<int>(
stream: device.mtu,
initialData: 0,
builder: (c, snapshot) => ListTile(
title: Text('MTU Size'),
subtitle: Text('${snapshot.data} bytes'),
trailing: IconButton(
icon: Icon(Icons.edit),
onPressed: () => device.requestMtu(223),
),
),
),
StreamBuilder<List<BluetoothService>>(
stream: device.services,
initialData: [],
builder: (c, snapshot) {
return Column(
children: _buildServiceTiles(snapshot.data),
);
},
),
],
),
),
);
}
}
I figured it out, I had my characteristic UUID to be 6e400002-b5a3-f393-e0a9-e50e24dcca9e and it should have been 6e400003-b5a3-f393-e0a9-e50e24dcca9e because for the feather, the notification/notify characteristic is mandatory to be 0x0003 instead of the 2. It then passed the CCCD properly when I changed this value.
I'm building a URL shortner app. I want to show a loading screen after the url is entered. This is my code. I'm a beginner to flutter. Please help me since this is my first app. The code is given below. As you can see the I'm using FutureBuilder so if the url list is empty it shows a corresponding message but I want it to disappear after the ok button of the alertdialog is pressed.
class _homePageState extends State<homePage> {
List userURL = List();
List item = List();
Future<List> getdata() async {
//JSON Parser
var url = 'https://api.shrtco.de/v2/shorten?url=${userURL.last}';
var respons = await http.get(url);
var result = jsonDecode(respons.body);
item.add(result['result']['short_link']); //dictionary parse
print(item);
return item;
}
createAlertDialog(BuildContext context) {
//method for alertdialog
//promise to return string
TextEditingController customController =
TextEditingController(); //new texteditingc object
return showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text("Enter URL: "),
content: TextField(
controller: customController,
),
actions: [
MaterialButton(
elevation: 5.0,
child: Text("OK"),
onPressed: () {
if (customController.text != null &&
customController.text != "") {
userURL.add(customController.text);
}
setState(() {});
Navigator.of(context).pop();
},
)
],
);
});
}
#override
Widget build(BuildContext context) {
String temp;
return Scaffold(
appBar: AppBar(
title: Text("Shortie"),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: FutureBuilder(
future: getdata(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.sentiment_very_dissatisfied,
color: Colors.grey,
size: 80,
),
Text(
"No short links to display",
style: TextStyle(
color: Colors.grey[700],
fontSize: 15,
//fontWeight: FontWeight.bold
),
),
]));
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return ListTile(
leading: Icon(Icons.link),
title: Text(snapshot.data[index]),
subtitle: Text(userURL[index]),
onTap: () {
Share.share(
'Check out the short link I just shared with the application Shortie: ${snapshot.data[index]}',
subject: 'Shortie short link');
print(snapshot.data[index]);
},
);
},
);
}
},
)),
floatingActionButton: FloatingActionButton(
onPressed: () {
createAlertDialog(context).then((onValue) {
temp = onValue;
print(temp);
});
You can make use of the connection state class of the FutureBuilder as follows:
FutureBuilder(
future: getdata(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator(backgroundColor: Colors.blue);
} else {
return Container();
}
},
);
Also, on your button you need to call setState() to trigger the view reload, which in turn will again check the connectionState, if the async function is still in progress you will see the loading indicator, otherwise something you put in else