I am trying to create a detail screen to display my Firebase data from the database, and show the image along with some text data including the number of items, date, and geolocation. Is there a way to determine why the data is returning null? The navigator should navigate to the DetailPage.
Here is my Main file -
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:wasteagram/pages/create_waste.dart';
import 'package:wasteagram/services/crud.dart';
import 'pages/create_waste.dart';
import 'pages/detail_screen.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Wasteagram - ',
theme: new ThemeData(
primarySwatch: Colors.deepOrange,
),
home: new MyHomePage(title: 'Wasteagram - '),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
CrudMethods crudMethods = new CrudMethods();
Stream wasteStream;
Widget WasteList() {
return Container(
child: wasteStream != null ? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
StreamBuilder(
stream: wasteStream,
builder: (context, snapshot) {
return ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 16),
itemCount: snapshot.data.documents.length,
shrinkWrap: true,
itemBuilder: (context, index){
return WidgetTile(
wastedate:
snapshot.data.documents[index].data['wastedate'],
wastenumber:
snapshot.data.documents[index].data['wastenumber']
);
});
},)
],
) : Container(
alignment: Alignment.center,
child: CircularProgressIndicator(),
),
);
}
void initState() {
super.initState();
crudMethods.getData().then((result) {
wasteStream = result;
});
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: WasteList(),
floatingActionButton: new FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => CameraScreen())
);
},
child: new Icon(Icons.add),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
);
}
}
class WidgetTile extends StatelessWidget {
String wastedate, wastenumber;
WidgetTile({#required this.wastedate, #required this.wastenumber});
#override
Widget build(BuildContext context) {
return ListTile(
title: Text(wastedate),
trailing: Text(wastenumber),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => DetailPage())
);
}
);
}
}
Here is my detail_screen.dart
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:wasteagram/data/firestore_service.dart';
class DetailPage extends StatefulWidget {
final DocumentSnapshot post;
DetailPage({this.post});
#override
_DetailPageState createState() => _DetailPageState();
}
class _DetailPageState extends State<DetailPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.post.data["wastedate"])
),
body: Center(
child: Container(
child: Column(
children: <Widget> [
Image.network(widget.post.data["image"]),
Text(widget.post.data["wastedate"]),
Text(widget.post.data["wastenumber"]),
Text(widget.post.data["wastelocation"].toString()),
]
)
)
),
);
}
}
You are not passing DocumentSnapshot to Detail Page.
Try this:
Widget WasteList() {
return Container(
child: wasteStream != null ? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
StreamBuilder(
stream: wasteStream,
builder: (context, snapshot) {
return ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 16),
itemCount: snapshot.data.documents.length,
shrinkWrap: true,
itemBuilder: (context, index){
return WidgetTile(
wastedate:
snapshot.data.documents[index].data['wastedate'],
wastenumber:
snapshot.data.documents[index].data['wastenumber'],
post:
snapshot.data.documents[index]
);
});
},)
],
) : Container(
alignment: Alignment.center,
child: CircularProgressIndicator(),
),
);
}
class WidgetTile extends StatelessWidget {
String wastedate, wastenumber;
DocumentSnapshot post;
WidgetTile({#required this.wastedate, #required this.wastenumber,#required this.post});
#override
Widget build(BuildContext context) {
return ListTile(
title: Text(wastedate),
trailing: Text(wastenumber),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => DetailPage(post: post))
);
}
);
}
}
Related
Making a list with adding items to the database. After switching from main.dart to the page with a list, it does not open, it writes an error.enter image description here
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
#override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
late String _userToDo;
List todoList = [];
void initFirebase() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(Home());
}
#override
void initState() {
super.initState();
initFirebase();
todoList.addAll(['Milk', 'Car', 'Sugar']);
}
void _menuOpen() {
Navigator.of(context).push(
MaterialPageRoute(builder: (BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Menu'),),
body: Row(
children: [
Padding(padding: EdgeInsets.only(left: 15)),
ElevatedButton(onPressed: () {
Navigator.pop(context);
Navigator.pushNamedAndRemoveUntil(context, '/', (route) => false);
},
child: Text('Home')),
Padding(padding: EdgeInsets.only(left: 15)),
Text('Home old')
],
)
);
})
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[900],
appBar: AppBar(
title: Text('Список дел'),
actions: [
IconButton(onPressed: _menuOpen,
icon: Icon(Icons.menu_outlined),
)
],
),
body: ListView.builder(
itemCount: todoList.length,
itemBuilder: (BuildContext context, int index){
return Dismissible(
key: Key(todoList[index]),
child: Card(
child: ListTile(
title: Text(todoList[index]),
trailing: IconButton(
icon: Icon(Icons.delete_sweep,
color: Colors.redAccent,
), onPressed: () {
setState(() {
todoList.removeAt(index);
});
},
)
),
),
onDismissed: (direction) {
// if(direction == DismissDirection.startToEnd)
setState(() {
todoList.removeAt(index);
});
},
);
}
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.green,
onPressed: () {
showDialog(context: context, builder: (BuildContext context){
return AlertDialog(
title: Text('Добавить'),
content: TextField(
onChanged: (String value){
_userToDo = value;
},
),
actions: [
ElevatedButton(onPressed: (){
FirebaseFirestore.instance.collection('items').add({'item': _userToDo});
Navigator.of(context).pop();
}, child: Text('Добавить')
)
],
);
});
},
child: Icon(Icons.add_comment_outlined,
color: Colors.white,
),
),
);
}
}
Everyone knows the error.
The following assertion was thrown building Home(state:
_HomeState#17f50): No MediaQuery widget ancestor found.
Scaffold widgets require a MediaQuery widget ancestor. The specific
widget that could not find a MediaQuery ancestor was: Scaffold dirty
state: ScaffoldState#4d9ee(lifecycle state: initialized, tickers:
tracking 2 tickers) The ownership chain for the affected widget is:
"Scaffold ← Home ← [root]"
No MediaQuery ancestor could be found starting from the context that
was passed to MediaQuery.of(). This can happen because you have not
added a WidgetsApp, CupertinoApp, or MaterialApp widget (those widgets
introduce a MediaQuery), or it can happen if the context you use comes
from a widget above those widgets.
Set according to your advice. Navigation and pop-up window stopped working.
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
#override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
late String _userToDo;
List todoList = [];
void initFirebase() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(Home());
}
#override
void initState() {
super.initState();
initFirebase();
todoList.addAll(['Milk', 'Car', 'Sugar']);
}
void _menuOpen() {
Navigator.of(context).push(
MaterialPageRoute(builder: (BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Menu'),),
body: Row(
children: [
Padding(padding: EdgeInsets.only(left: 15)),
ElevatedButton(onPressed: () {
Navigator.pop(context);
Navigator.pushNamedAndRemoveUntil(context, '/', (route) => false);
},
child: Text('Home')),
Padding(padding: EdgeInsets.only(left: 15)),
Text('Home old')
],
)
);
})
);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.grey[900],
appBar: AppBar(
title: Text('Список дел'),
actions: [
IconButton(onPressed: _menuOpen,
icon: Icon(Icons.menu_outlined),
)
],
),
body: ListView.builder(
itemCount: todoList.length,
itemBuilder: (BuildContext context, int index){
return Dismissible(
key: Key(todoList[index]),
child: Card(
child: ListTile(
title: Text(todoList[index]),
trailing: IconButton(
icon: Icon(Icons.delete_sweep,
color: Colors.redAccent,
), onPressed: () {
setState(() {
todoList.removeAt(index);
});
},
)
),
),
onDismissed: (direction) {
// if(direction == DismissDirection.startToEnd)
setState(() {
todoList.removeAt(index);
});
},
);
}
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.green,
onPressed: () {
showDialog(context: context, builder: (BuildContext context){
return AlertDialog(
title: Text('Добавить'),
content: TextField(
onChanged: (String value){
_userToDo = value;
},
),
actions: [
ElevatedButton(onPressed: (){
FirebaseFirestore.instance.collection('items').add({'item': _userToDo});
Navigator.of(context).pop();
}, child: Text('Добавить')
)
],
);
});
},
child: Icon(Icons.add_comment_outlined,
color: Colors.white,
),
),
),
);
}
}
The following assertion was thrown while handling a gesture: No
MaterialLocalizations found.
Home widgets require MaterialLocalizations to be provided by a
Localizations widget ancestor. The material library uses Localizations
to generate messages, labels, and abbreviations.
To introduce a MaterialLocalizations, either use a MaterialApp at the
root of your application to include them automatically, or add a
Localization widget with a MaterialLocalizations delegate.
The specific widget that could not find a MaterialLocalizations
ancestor was: Home state: _HomeState#8899d The ancestors of this
widget were: : [root]
renderObject: RenderView#1dbbb
void initFirebase() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(Home());
}
With that runApp call, you are removing your entire widget tree and replacing it with a tree rooted at a Home widget. This means that you are unable to access the MaterialApp widget that is presumably built by your App widget elsewhere in your app.
To fix this, move the first two lines of this method to your main method before runApp, and remove the entire method from the Home widget.
Part of the error says: This can happen because you have not added a WidgetsApp, CupertinoApp, or MaterialApp widget.
So in your Build method, you can wrap your Scaffold with a MaterialApp() and it should work.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(...),
);
}
i'm new in flutter world. i'm using bottom navigation bar but i don't have idea how to pass data from bottom navigation bar page to homepage since homepage is expecting 1 parameter. i'm passing data between other pages but i couldn't find a way to pass data between bottomnavigation bar and home page. any help would be apprecaited
thanks in advance
this is my navigation page code
import 'package:chat_app/models/user_model.dart';
import 'package:chat_app/screens/call_log_screen.dart';
import 'package:chat_app/screens/chat_screen.dart';
import 'package:chat_app/screens/home_screen.dart';
import 'package:chat_app/screens/search_screen.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class CustomBottomNavigationBar extends StatefulWidget {
UserModel user;
CustomBottomNavigationBar(this.user);
#override
_CustomBottomNavigationBarState createState() =>
_CustomBottomNavigationBarState();
}
class _CustomBottomNavigationBarState extends State<CustomBottomNavigationBar> {
int _selectedIndex = 0;
late final screens = [
HomeScreen(widget.user),
CallLog(),
CallLog(),
CallLog(),
];
void onTapped(int index) {
print(widget.user.name);
setState(() {
_selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: screens[_selectedIndex],
bottomNavigationBar: BottomNavigationBar(
backgroundColor: Colors.black,
selectedIconTheme: IconThemeData(color: Colors.blue),
currentIndex: 2,
items: [
BottomNavigationBarItem(
icon: Icon(
CupertinoIcons.settings,
color: Colors.grey,
),
label: 'hi',
),
BottomNavigationBarItem(
icon: Icon(
CupertinoIcons.home,
color: Colors.grey,
),
label: 'hi',
),
BottomNavigationBarItem(
icon: Icon(
CupertinoIcons.phone,
color: Colors.grey,
),
label: 'hi',
),
BottomNavigationBarItem(
icon: Icon(
CupertinoIcons.chat_bubble_text,
color: Colors.grey,
),
label: 'hi',
),
],
onTap: onTapped,
),
);
}
}
and this is my homepage code
import 'package:cached_network_image/cached_network_image.dart';
import 'package:chat_app/models/user_model.dart';
import 'package:chat_app/screens/chat_screen.dart';
import 'package:chat_app/screens/search_screen.dart';
import 'package:chat_app/widgets/bottom_navigation_bar.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:intl/intl.dart';
import 'auth_screen.dart';
class HomeScreen extends StatefulWidget {
UserModel user;
HomeScreen(this.user);
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
#override
void initState() {
// TODO: implement initState
super.initState();
WidgetsBinding.instance!.addObserver(this);
setStatus('online');
}
void setStatus(String status) async {
await FirebaseFirestore.instance
.collection('users')
.doc(widget.user.uid)
.update({"userStatus": status});
}
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
// TODO: implement didChangeAppLifecycleState
if (state == AppLifecycleState.resumed) {
//online
setStatus("online");
} else {
//offline
setStatus('offline');
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
centerTitle: true,
backgroundColor: Colors.deepPurple,
actions: [
IconButton(
onPressed: () async {
await GoogleSignIn().signOut();
await FirebaseAuth.instance.signOut();
setStatus('offline');
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) => AuthScreen(),
),
(route) => false);
},
icon: Icon(Icons.logout),
),
],
),
body: StreamBuilder(
stream: FirebaseFirestore.instance
.collection('users')
.doc(widget.user.uid)
.collection('messages')
.snapshots(),
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
if (snapshot.data.docs.length < 1) {
return Center(
child: Text('No Chat Available!!!'),
);
}
return ListView.builder(
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
var friendId = snapshot.data.docs[index].id;
var lastMsg = snapshot.data.docs[index]['last_message'];
var lastMsgTime =
snapshot.data.docs[index]['last_message_time'];
return FutureBuilder(
future: FirebaseFirestore.instance
.collection('users')
.doc(friendId)
.get(),
builder: (context, AsyncSnapshot asyncSnapShot) {
if (asyncSnapShot.hasData) {
var friend = asyncSnapShot.data;
return ListTile(
leading: ClipRRect(
borderRadius: BorderRadius.circular(80.0),
child: CachedNetworkImage(
imageUrl: friend['image'],
placeholder: (context, url) =>
CircularProgressIndicator(),
errorWidget: (context, url, error) =>
Icon(Icons.error),
),
// child: Image.network(
// friend['image'],
// ),
),
trailing: Text(
DateFormat.jm().format(
lastMsgTime.toDate(),
),
),
title: Text(
friend['name'],
),
subtitle: Text(
"$lastMsg",
style: TextStyle(color: Colors.grey),
overflow: TextOverflow.ellipsis,
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ChatScreen(
currentUser: widget.user,
receiverId: friend['uid'],
receiverImage: friend['image'],
receiverName: friend['name'],
),
),
);
},
);
}
return LinearProgressIndicator();
},
);
},
);
}
return Center(
child: CircularProgressIndicator(),
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SearchScreen(widget.user),
),
);
// Navigator.pushAndRemoveUntil(
// context,
// MaterialPageRoute(
// builder: (context) => SearchScreen(widget.user),
// ),
// (route) => false);
},
child: Icon(CupertinoIcons.search),
),
bottomNavigationBar: CustomBottomNavigationBar(widget.user),
);
}
}
You can't access instance member widget in an initializer.
Try this
class _CustomBottomNavigationBarState extends State<CustomBottomNavigationBar> {
int _selectedIndex = 0;
late final List screens;
#override
void initState() {
super.initState();
screens = [
HomeScreen(widget.user),
CallLog(),
CallLog(),
CallLog(),
];
}
...
// the rest of your code
I want to retrieve array from firebase or cloud_firestore.
I have no problem with retrieving single data but i am having problem with retrieving array data
please help my beginner mind is at the verge of exploding.
I have google it and gone through many tutorials videos but i can't find the solution
database image here
pubspec.yaml
dependencies:
cloud_firestore: ^0.13.6
main.dart
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Scaffold(
appBar: AppBar(title: Text("Flutter Fire CRUD")),
body: ListPage(),
),
);
}
}
class ListPage extends StatefulWidget {
#override
_ListPageState createState() => _ListPageState();
}
class _ListPageState extends State<ListPage> {
Future _data;
Future getUsers() async {
var firestore = Firestore.instance;
firestore.collection("users").getDocuments();
QuerySnapshot qn = await firestore.collection("users").getDocuments();
return qn.documents;
}
navigateToDetail(DocumentSnapshot users) {
Navigator.push(context,
MaterialPageRoute(builder: (context) => DetailList(users: users)));
}
#override
void initState() {
super.initState();
_data = getUsers();
}
#override
Widget build(BuildContext context) {
return Container(
child: FutureBuilder(
future: _data,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading ...");
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(snapshot.data[index].data['name']),
onTap: () {
navigateToDetail(snapshot.data[index]);
});
},
);
}
},
),
);
}
}
class DetailList extends StatefulWidget {
final DocumentSnapshot users;
DetailList({Key key, #required this.users}) : super(key: key);
#override
_DetailListState createState() => _DetailListState();
}
class _DetailListState extends State<DetailList> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("${widget.users.data['name']}"),
),
body: Column(
children: [
Container(
height: MediaQuery.of(context).size.height / 2.0,
width: MediaQuery.of(context).size.width,
child: Center(
child: Image.network(widget.users.data["img"]),
),
),
Container(
child: Card(
child: ListTile(
title: Text(widget.users.data["name"]),
subtitle: Text("Age:" + widget.users.data["age"]),
),
),
),
ListView.builder(
itemCount: widget.users.data["skills"],
itemBuilder: (context, index) {
return ListTile(
//title: Text(widget.users.data["skills"][index]),
title: here............
);
},
)
],
),
);
}
}
StreamBuilder(
stream: Firestore.instance
.collection('users')
.document(id)
.collection('chatWith')
.orderBy('timestamp', descending: true)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(
AppColor.colorCustom),
),
);
} else {
if (snapshot.data.documents.length == 0) {
return Container(
alignment: Alignment.center,
child: Text(
"No Chat History Found",
style: TextStyle(
color: Colors.grey,
fontWeight: FontWeight.normal,
fontSize:
Util.px_23 * SizeConfig.textMultiplier,
fontFamily: 'Roboto',
),
softWrap: true,
),
);
} else {
return ListView.builder(
padding: EdgeInsets.all(
Util.px_10 * SizeConfig.heightMultiplier),
itemBuilder: (context, index) => _listItem(
context, snapshot.data.documents[index]),
itemCount: snapshot.data.documents.length,
);
}
}
},
)
You can fetch list of data from firestore. this code I have used in my project. You can modify as per your requirement.
https://i.stack.imgur.com/9k5MB.png
I am new to flutter and I'm working on social distancing app in flutter. I wanted to push the uuid of bluetooth devices discovered to the firestore can someone please help me in doing this
I can print out the discovered devices in my app and i can get rssi uuid txpower
but as rssi keeps varying and scanning happens continuously the devices get pushed into firestore multiple times
i wanted UUID to be pushed into the firestore only once.
Nearby.dart
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_blue/flutter_blue.dart';
import 'package:beacon_broadcast/beacon_broadcast.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'homescreen.dart';
import 'material.dart';
class BlueApp extends StatefulWidget {
#override
_BlueAppState createState() => _BlueAppState();
}
BeaconBroadcast beaconBroadcast = BeaconBroadcast();
BeaconStatus _isTransmissionSupported;
bool _isAdvertising = false;
StreamSubscription<bool> _isAdvertisingSubscription;
final databaseReference=Firestore.instance;
String UUID = "3E4D7TJ9008";
void createRecord(String usid) async {
await databaseReference.collection("users")
.document("1")
.setData({
'uuid':usid
});
print('senddddddddingggggg');
DocumentReference ref = await databaseReference.collection("users")
.add({
'uuid':usid
});
print(ref.documentID);
}
class _BlueAppState extends State<BlueApp> {
static const UUID = '39ED98FF';
static const MAJOR_ID = 1;
static const MINOR_ID = 100;
static const TRANSMISSION_POWER = -59;
static const IDENTIFIER = 'com.example.myDeviceRegion';
static const LAYOUT = BeaconBroadcast.ALTBEACON_LAYOUT;
static const MANUFACTURER_ID = 0x0118;
void initState() {
// TODO: implement initState
super.initState();
FlutterBlue.instance.state.listen((state) {
print("im in the init");
print(state);
if (state == BluetoothState.off) {
print("bluetooth is off");
} else if (state == BluetoothState.on) {
print("bluethooth on");
//print(device.id);
}
print("printing eacon");
});
beaconBroadcast.checkTransmissionSupported().then((isTransmissionSupported) {
setState(() {
_isTransmissionSupported = isTransmissionSupported;
print(_isTransmissionSupported);
});
});
_isAdvertisingSubscription =
beaconBroadcast.getAdvertisingStateChange().listen((isAdvertising) {
setState(() {
_isAdvertising = isAdvertising;
});
});
beaconBroadcast
.setUUID(UUID)
.setMajorId(MAJOR_ID)
.setMinorId(MINOR_ID)
.setTransmissionPower(-59)
.setIdentifier(IDENTIFIER)
.setLayout(LAYOUT)
.setManufacturerId(MANUFACTURER_ID)
.start();
if(_isAdvertising==true){
print('Beacon started Advertising');
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
color: Colors.lightBlue,
home: StreamBuilder<BluetoothState>(
stream: FlutterBlue.instance.state,
initialData: BluetoothState.turningOn,
builder: (c, snapshot) {
final state = snapshot.data;
print(state);
if (state == BluetoothState.on) {
print("BlueTooth is on");
return FindDevicesScreen();
}
print("BlueTooth is off");
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) {
_BlueAppState a=new _BlueAppState();
createRecord(UUID);
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 != null ? state.toString().substring(15) : 'not available'}.',
style: Theme.of(context)
.primaryTextTheme
.subhead
.copyWith(color: Colors.white),
),
],
),
),
);
}
}
class FindDevicesScreen extends StatefulWidget {
#override
_FindDevicesScreenState createState() => _FindDevicesScreenState();
}
class _FindDevicesScreenState extends State<FindDevicesScreen> {
#override
void initState() {
// TODO: implement initState
super.initState();
FlutterBlue.instance.startScan();
beaconBroadcast.checkTransmissionSupported().then((isTransmissionSupported) {
setState(() {
_isTransmissionSupported = isTransmissionSupported;
print(_isTransmissionSupported);
});
});
_isAdvertisingSubscription =
beaconBroadcast.getAdvertisingStateChange().listen((isAdvertising) {
setState(() {
_isAdvertising = isAdvertising;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Find Devices'),
),
body: RefreshIndicator(
onRefresh: () =>
FlutterBlue.instance.startScan(),
child: SingleChildScrollView(
child: Column(
children: <Widget>[
StreamBuilder<List<BluetoothDevice>>(
stream: Stream.periodic(Duration(seconds: 4))
.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) {
print('entering if');
if (true) {
print('id----------------------------------------------did');
}
return Text(snapshot.data.toString());
},
),
))
.toList(),
),
),
StreamBuilder<List<ScanResult>>(
stream: FlutterBlue.instance.scanResults,
initialData: [],
builder: (c, snapshot) => Column(
children: snapshot.data
.map(
(r) => Card(
child: ScanResultTile(
result: r,
onTap: () => Navigator.of(context)
.push(MaterialPageRoute(builder: (context) {
return null;
})),
),
),
)
.toList(),
),
),
],
),
),
),
);
}
}
material.dart
import 'package:flutter_blue/flutter_blue.dart';
import 'nearby.dart';
class ScanResultTile extends StatelessWidget {
const ScanResultTile({Key key, this.result, this.onTap}) : super(key: key);
final ScanResult result;
final VoidCallback onTap;
Widget _buildTitle(BuildContext context) {
if (result.device.name.length > 0) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
result.device.name,
overflow: TextOverflow.ellipsis,
),
Text(
result.device.id.toString(),
style: Theme.of(context).textTheme.caption,
),
// _buildAdvRow(
// context, 'Distance of the device',(result.rssi!=null && result.advertisementData.txPowerLevel!=null)?"${getDistance(result.rssi,result.advertisementData.txPowerLevel)}":"N/A" ),
],
);
} else {
return Text(result.device.id.toString());
}
}
Widget _buildAdvRow(BuildContext context, String title, String value) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 4.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(title, style: Theme.of(context).textTheme.caption),
SizedBox(
width: 12.0,
),
Expanded(
child: Text(
value,
style: Theme.of(context)
.textTheme
.caption
.apply(color: Colors.black),
softWrap: true,
),
),
],
),
);
}
String getNiceHexArray(List<int> bytes) {
return '[${bytes.map((i) => i.toRadixString(16).padLeft(2, '0')).join(', ')}]'
.toUpperCase();
}
int getDistance(int rssi, int txPower) {
print("rssi");
print(rssi);
return 10 ^ ((txPower - rssi) / (10 * 2)).round();
}
#override
Widget build(BuildContext context) {
print("rssi");
print(result.rssi);
print("Transmit power");
print(result.advertisementData.txPowerLevel);
// print(result.device.name);
print(result);
// if((getDistance(result.rssi,result.advertisementData.txPowerLevel))<=2)
// {
// createRecord(result.advertisementData.serviceUuids.iterator.moveNext().toString());
// }
return ExpansionTile(
title: _buildTitle(context),
leading: Column(
children: <Widget>[
Text("Tap for more...",style: TextStyle(fontSize: 10.0,color: Colors.lightBlueAccent),)
],
),
children: <Widget>[
_buildAdvRow(
context, 'Distance of the device',(result.rssi!=null && result.advertisementData.txPowerLevel!=null)?"${getDistance(result.rssi,result.advertisementData.txPowerLevel)}":"N/A" ),
_buildAdvRow(context, 'Tx Power Level',
'${result.advertisementData.txPowerLevel ?? 'N/A'}'),
_buildAdvRow(
context,
'Service UUIDs',
(result.advertisementData.serviceUuids.isNotEmpty)? result.advertisementData.serviceUuids.join(', ').toUpperCase(): 'N/A'),
],
);
}
}
class ServiceTile extends StatelessWidget {
final BluetoothService service;
final List<CharacteristicTile> characteristicTiles;
const ServiceTile({Key key, this.service, this.characteristicTiles})
: super(key: key);
#override
Widget build(BuildContext context) {
if (characteristicTiles.length > 0) {
return ExpansionTile(
title: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Service'),
Text('0x${service.uuid.toString().toUpperCase().substring(4, 8)}',
style: Theme.of(context)
.textTheme
.body1
.copyWith(color: Theme.of(context).textTheme.caption.color))
],
),
children: characteristicTiles,
);
} else {
return ListTile(
title: Text('Service'),
subtitle:
Text('0x${service.uuid.toString().toUpperCase().substring(4, 8)}'),
);
}
}
}
class CharacteristicTile extends StatelessWidget {
final BluetoothCharacteristic characteristic;
final List<DescriptorTile> descriptorTiles;
final VoidCallback onReadPressed;
final VoidCallback onWritePressed;
final VoidCallback onNotificationPressed;
const CharacteristicTile(
{Key key,
this.characteristic,
this.descriptorTiles,
this.onReadPressed,
this.onWritePressed,
this.onNotificationPressed})
: super(key: key);
#override
Widget build(BuildContext context) {
return StreamBuilder<List<int>>(
stream: characteristic.value,
initialData: characteristic.lastValue,
builder: (c, snapshot) {
final value = snapshot.data;
return ExpansionTile(
title: ListTile(
title: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Characteristic'),
Text(
'0x${characteristic.uuid.toString().toUpperCase().substring(4, 8)}',
style: Theme.of(context).textTheme.body1.copyWith(
color: Theme.of(context).textTheme.caption.color))
],
),
subtitle: Text(value.toString()),
contentPadding: EdgeInsets.all(0.0),
),
children: descriptorTiles,
);
},
);
}
}
class DescriptorTile extends StatelessWidget {
final BluetoothDescriptor descriptor;
final VoidCallback onReadPressed;
final VoidCallback onWritePressed;
const DescriptorTile(
{Key key, this.descriptor, this.onReadPressed, this.onWritePressed})
: super(key: key);
#override
Widget build(BuildContext context) {
return ListTile(
title: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Descriptor'),
Text('0x${descriptor.uuid.toString().toUpperCase().substring(4, 8)}',
style: Theme.of(context)
.textTheme
.body1
.copyWith(color: Theme.of(context).textTheme.caption.color))
],
),
subtitle: StreamBuilder<List<int>>(
stream: descriptor.value,
initialData: descriptor.lastValue,
builder: (c, snapshot) => Text(snapshot.data.toString()),
),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
IconButton(
icon: Icon(
Icons.file_download,
color: Theme.of(context).iconTheme.color.withOpacity(0.5),
),
onPressed: onReadPressed,
),
IconButton(
icon: Icon(
Icons.file_upload,
color: Theme.of(context).iconTheme.color.withOpacity(0.5),
),
onPressed: onWritePressed,
)
],
),
);
}
}
class AdapterStateTile extends StatelessWidget {
const AdapterStateTile({Key key, #required this.state}) : super(key: key);
final BluetoothState state;
#override
Widget build(BuildContext context) {
return Container(
color: Colors.redAccent,
child: ListTile(
title: Text(
'Bluetooth adapter is ${state.toString().substring(15)}',
style: Theme.of(context).primaryTextTheme.subhead,
),
trailing: Icon(
Icons.error,
color: Theme.of(context).primaryTextTheme.subhead.color,
),
),
);
}
}```
To avoid adding it additional times there are two altenatives.
Alternative 1:
Index the uuid field, as this will allow you to query over this field
Before writing query for documents with this uuid
Write only if the response is empty
This alternative has the advantage that no changes need to be done on firestore and minimun changes on the code, however will have the disadvantage that each write attempt will be preceeded by a read and reads are billed.
Alternative 2:
Change the data structucture on Firestore so that the UUID is the document ID
This has the advantage that the writes won't be preceeded by a read therefore its cheaper on firestore costs. However it needs more code edition and will need to change the data stucture.
for the code the main change is on the following method:
void createRecord(String usid) async {
await databaseReference.collection("users")
.document(usid)
.setData({
'uuid':usid
});
print('senddddddddingggggg');
DocumentReference ref = await databaseReference.collection("users")
.document(usid)
.setData({
'uuid':usid
});
print(ref.documentID);
}
1) This is the view team/view roster screen. https://imgur.com/a/k63lQrt
class ViewTeamScreen extends StatelessWidget {
static const routeName = '/view-team';
const ViewTeamScreen({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return StreamProvider<List<User>>.value(
value: DBService().getAllUsers,
child: Scaffold(
body: TeamList()
),
);
}
}
2) This is the team list code that displays all user data on the ViewTeamScreen and returns a TeamTile widget i created.
class TeamList extends StatefulWidget {
#override
_TeamListState createState() => _TeamListState();
}
class _TeamListState extends State<TeamList> {
#override
Widget build(BuildContext context) {
final users = Provider.of<List<User>>(context) ?? [];
//print(users);
return ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
return TeamTile(
user: users[index],
);
},
);
3) This is the TeamTile, which returns ListViewBuilder for a team member once they sign up to the app.
class TeamTile extends StatelessWidget {
final User user;
TeamTile({this.user});
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.only(top: 8.0),
child: Card(
margin: EdgeInsets.fromLTRB(20, 6, 20, 0),
child: ListTile(
leading: CircleAvatar(
radius: 30.0,
backgroundColor: Colors.brown,
),
title: Text(
'${user.firstName}'
" "
'${user.lastName}', //how do i make the first letter of name always CAPS?
style: TextStyle(fontSize: 23, letterSpacing: 1.0),
),
trailing: Text(user.email),
subtitle: Text('+44 0000 000 000'),
onTap: () async {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => TeamDetailScreen(),
),
);
},
),
4) This is the team detail screen, once the user taps on the ListTile in the ViewTeamScreen, this page will apear. https://imgur.com/a/7tSUO1c
class TeamDetailScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
return Scaffold(
appBar: AppBar(
title: Text('Employee Contact Info'),
),
body: StreamBuilder<User>(
stream: DBService(uid: user.uid).usersData,
builder: (context, snapshot) {
if (snapshot.hasData) {
User userData = snapshot.data;
return Column(children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Name: ${userData.firstName}'
" "
'${userData.lastName}\n'
'Email: ${userData.email}',
style: TextStyle(fontSize: (20)),
),
)),
]);
} else {
return Loading();
This is going to exclude StreamProvider and just use StreamBuilder. This concept is easy to understand, as all we are doing is passing the widget.index down to other Widgets as arguments.
1
class ViewTeamScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StreamBuilder<List<User>>(
stream: DBService().getAllUsers,
builder: (context, snapshot) {
if (snapshot.hasData) {
List<User> userData = snapshot.data;
return Scaffold(body: TeamList(myData: userData));
} else {
return Loading();
}
});
}
}
2
class TeamList extends StatefulWidget {
final List<User> myData;
TeamList({this.myData});
#override
_TeamListState createState() => _TeamListState();
}
class _TeamListState extends State<TeamList> {
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: widget.myData.length,
itemBuilder: (context, index) {
return TeamTile(
usersInfo: widget.myData[index],
);
},
);
}
}
3
class TeamTile extends StatelessWidget {
final User usersInfo;
TeamTile({this.usersInfo});
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.only(top: 8.0),
child: Card(
margin: EdgeInsets.fromLTRB(20, 6, 20, 0),
child: ListTile(
leading: CircleAvatar(
radius: 30.0,
backgroundColor: Colors.brown,
),
title: Text(
'${usersInfo.firstName}'
" "
'${usersInfo.lastName}', //how do i make the first letter of name always CAPS?
style: TextStyle(fontSize: 23, letterSpacing: 1.0),
),
trailing: Text(usersInfo.email),
subtitle: Text('+44 0000 000 000'),
onTap: () async {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => TeamDetailScreen(myDetails: usersInfo),
),
);
},
),
),
);
}
}
4
class TeamDetailScreen extends StatelessWidget {
final User myDetails;
TeamDetailScreen({this.myDetails});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Name: ${myDetails.firstName}'
" "
'${myDetails.lastName}\n'
'Email: ${myDetails.email}',
style: TextStyle(fontSize: (20)),
),
)),
]),
);
}
}