Flutter display firebase storage image from path - firebase

I have been reading some questions around this and I can't find anything really that is relevant to what I am trying to do, and what I am trying to do is very simple.
I have the path of an image file from Firebase Storage, say:
SharedPreferences prefs = await SharedPreferences.getInstance();
String fileName = prefs.getString('currentProfileImage');
StorageReference storageReference = FirebaseStorage.instance
.ref()
.child(widget.currentUserUID.toString() + '/profile/' + fileName);
So the image file path will be something like:
b8sJ7cEHCFdjh46wZNp5xThbvVzz2/profile/image_picker209656937087714.jpg
I just want to display this image. That's all. How can I convert knowing the exact path to this file into an object of type Image?

You need to save the image first to Firebase Storage using putFile():
StorageTaskSnapshot snapshot = await storage
.ref()
.child(widget.currentUserUID.toString() + '/profile/' + fileName)
.putFile(file)
.onComplete;
Then you get the url of the image in Firebase Storage and save it to Firestore, for example:
final String downloadUrl =
await snapshot.ref.getDownloadURL();
await Firestore.instance
.collection("images")
.add({"url": downloadUrl, "name": imageName});
Then to display the image you can do the following:
body: Container(
padding: EdgeInsets.all(10.0),
child: FutureBuilder(
future: getImages(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.documents.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
contentPadding: EdgeInsets.all(8.0),
title:
Text(snapshot.data.documents[index].data["name"]),
leading: Image.network(
snapshot.data.documents[index].data["url"],
fit: BoxFit.fill),
);
});
} else if (snapshot.connectionState == ConnectionState.none) {
return Text("No data");
}
return CircularProgressIndicator();
},
),
),
/// code here
Future<QuerySnapshot> getImages() {
return fb.collection("images").getDocuments();
}
getImages() will retrieve the data inside the collection, then Image.network will take the url of the image and display the image in the application.

Related

Flutter: Streambuilder for documents from query

How do I get a listview of all the items returned from query snapshot?
FirebaseFirestore.instance
.collection("children")
.where("parentUID", isEqualTo: uid)
.snapshots()
.listen((result) {
result.docs.forEach((result) {
setState(() {
childFirstName = result["childFirstName"];
childLastName = result["childLastName"];
points = result["points"];
docID = result.id;
print('$docID');
});
});
});
}
This is all I could come up with, here is an image of the database,
Image of database
How can I make a listview which creates an item for every document which the parentUID is equal to the current users uid which is already stored in a variable uid
You can use the sample code below.
It shows how to use the stream from your query and return a ListView.builder which displays the information in a ListTile.
StreamBuilder<QuerySnapshot<Map<String, dynamic>>>(
stream: FirebaseFirestore.instance
.collection('children')
.where('parentUID', isEqualTo: uid)
.snapshots(),
builder: (BuildContext context, snapshot) {
if (snapshot.data == null) {
return Center(child: CircularProgressIndicator());
} else {
final List<QueryDocumentSnapshot<Map<String, dynamic>>> docs = snapshot.data!.docs;
return ListView.builder(
itemCount: docs.length,
itemBuilder: (_, index) {
final doc = docs[index];
final childFirstName = doc["childFirstName"];
final childLastName = doc["childLastName"];
final points = doc["points"];
final docID = doc.id;
return ListTile(
title: Text('$childFirstName $childLastName'),
subtitle: Text(points),
);
},
);
}
},
)

'Future<QuerySnapshot>' is not a subtype of type 'Stream<dynamic>'?

Im struggling trying to use a streambuider. Im getting an error that says :
════════ Exception caught by widgets library ═══════════════════════════════════
The following _TypeError was thrown building StreamBuilder<UserData>(dirty, state: _StreamBuilderBaseState<UserData, AsyncSnapshot<UserData>>#e2c02):
type 'Future<QuerySnapshot>' is not a subtype of type 'Stream<dynamic>' of 'function result'
heres my code
Stream myVideos;
getalldata() async {
//get videos as future
myVideos = FirebaseFirestore.instance
.collection('videos')
.where('uid', isEqualTo: widget.userid)
.snapshots();
var documents = await FirebaseFirestore.instance
.collection('videos')
.where('uid', isEqualTo: widget.userid)
.get();
if (documents.docs.isNotEmpty) {
for (var item in documents.docs) {
likes = item.data()['likes'].length + likes;
}
} else {
setState(() {
picturesdontexists = true;
});
}
setState(() {
dataisthere = true;
});
}
#override
Widget build(BuildContext context) {
final user = Provider.of<Userforid>(context);
return dataisthere == false
? Scaffold(body: Center(child: CircularProgressIndicator()))
: StreamBuilder<UserData>(
stream: DatbaseService(uid: user?.uid).userData,
builder: (context, snapshot) {
if (snapshot.hasData) {
UserData userData = snapshot.data;
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0.0,
- - - - - - - - - -
),
),
StreamBuilder(
stream: myVideos,
builder: ( context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
}
if(videos>0){
print(snapshot.data);
return StaggeredGridView.countBuilder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
physics: ScrollPhysics(),
crossAxisCount: 3,
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
DocumentSnapshot video =
snapshot.data.docs[index];
return InkWell(
onTap: () {
Navigator.of(context)
.pushNamed(ChatFirstpage.route);
},
child: Card(
elevation: 0.0,
What I think is that the error is thrown in the stream because before im using the stream myVideos im getting no error and all works fine .
Maye anyone can help Thank!. if you need more Information leave a comment .
Heres mine DatbaseService
class DatbaseService {
static DatbaseService instance = DatbaseService();
final String uid;
String _messages = "messages";
String _images = "images";
DatbaseService({this.uid});
//userData from snapshot
UserData userDataFromSnapshot(DocumentSnapshot snapshot) {
return UserData(
uid: uid,
email: snapshot.data()['email'],
fullname: snapshot.data()['fullname'],
password: snapshot.data()['password'],
url: snapshot.data()['url'],
username: snapshot.data()['username'],
);
}
//get user doc stream
Stream<UserData> get userData {
return myprofilsettings.doc(uid).snapshots().map(userDataFromSnapshot);
}
``
This usually arises when you are passing a Future where Stream should have gone or where you have defined the type of the variable as Stream but you are putting that variable equal to a future value.
I think instead of creating a variable like Stream myVideos you can directly put
FirebaseFirestore.instance
.collection('videos')
.where('uid', isEqualTo: widget.userid)
.snapshots()
inside the stream builder.
Also please provide the whole code (DatbaseService).

Flutter: Firestore Get User uid inside StreamBuilder

I have an app which I want to display documents inside collection.. the collection reference is the uid of the user.
Is there a way to get current user uid and put this uid inside StreamBuilder in stream.
I have tried like so but it did not work and returned null:
class _MyAdsState extends State<MyAds> {
final FirebaseAuth _auth = FirebaseAuth.instance;
Future getCurrentUser() async {
final FirebaseUser user = await _auth.currentUser();
final uid = user.uid;
print(uid);
return uid.toString();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
Expanded(
child: StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection("${getCurrentUser()}").snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> querySnapShot){
if(querySnapShot.hasError){
return Text('Some Error');
}
if(querySnapShot.connectionState == ConnectionState.waiting){
return CircularProgressIndicator();
}else{
final list = querySnapShot.data.documents;
return ListView.builder(
itemBuilder: (context, index){
return ListTile(
title: Text(list[index]["subject"]),
subtitle: Text(list[index]["category"]),
);
},
itemCount: list.length,
);
}
},
)
Getting the UID is an asynchronous operation, so requires a FutureBuilder.
If you want to use the UID to then build a stream, you'll need to have a FutureBuilder for the UID, and then inside of that a StreamBuilder for the stream from the database.
body: FutureBuilder(
future: FirebaseAuth.instance.currentUser(),
builder: (context, AsyncSnapshot<FirebaseUser> snapshot) {
if (snapshot.hasData) {
return StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection(snapshot.data.uid).snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> querySnapShot){
...
},
)
}
else {
return Text('Loading user data...');
}
THANK YOU GUYS!
I was looking for this for too long now. I had the "problem" that I was recording the senderUID for a sent message only, but of course wanted the Name being displayed in the "sentFrom" field. So I had to query Firestore for the UID and pull out the email. My solution:
FutureBuilder<QuerySnapshot>(
future: _firestore.collection("users").get(),
builder: (context, futureSnapshot) {
if (!futureSnapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
Map<String, String> users = {};
final userData = futureSnapshot.data.docs;
for (var user in userData) {
users[user.id] = user.data()["email"];
}
return StreamBuilder<QuerySnapshot>(
stream: _firestore.collection("messages").snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
// ignore: missing_return
final messages = snapshot.data.docs;
List<Widget> messageWidgets = [];
for (var message in messages) {
final messageText = message.data()["text"];
final messageEmail = users[message.data()["senderUID"]];
messageWidgets
.add(Text("$messageText from $messageEmail"));
}
return Column(children: messageWidgets);
},
);
},
),
I just created a map from the data and used it inside the stream builder. Is there maybe a better solution?

How to display image file in firestore with Flutter

I found following issue. Then I understand it.
Flutter / FireStore: how to display an image from Firestore in Flutter?
File uploading is succeeding.
var imgUrl = await ref.getDownloadURL();
print(imgUrl.toString());
However I have following error.
It seems I'm doing same.
Unhandled Exception: PlatformException(Error -13010, FIRStorageErrorDomain, Object images/cars/40711b90-9db4-11ea-c602-a557c9b7697a.jpeg does not exist.)
However I have no idea how to display and handle it.
Please give me advice. Thanks.
You need to add the url to firestore first:
StorageTaskSnapshot snapshot = await storage
.ref()
.child("images/$imageName")
.putFile(file)
.onComplete;
if (snapshot.error == null) {
final String downloadUrl =
await snapshot.ref.getDownloadURL();
await Firestore.instance
.collection("images")
.add({"url": downloadUrl, "name": imageName});
}
Now in Firestore you will have collection called images and document with the image url and image name. The method getDownloadUrl() returns the url of the image so you can store it in Firestore. Then to display it you can do the following:
body: Container(
padding: EdgeInsets.all(10.0),
child: FutureBuilder(
future: getImages(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.documents.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
contentPadding: EdgeInsets.all(8.0),
title:
Text(snapshot.data.documents[index].data["name"]),
leading: Image.network(
snapshot.data.documents[index].data["url"],
fit: BoxFit.fill),
);
});
} else if (snapshot.connectionState == ConnectionState.none) {
return Text("No data");
}
return CircularProgressIndicator();
},
),
),
/// code here
Future<QuerySnapshot> getImages() {
return fb.collection("images").getDocuments();
}
Here you use the method getImages() which retrieves all the images from the collection images. To display the image you can use Image.network widget.

I'm Having trouble accesing my data in firestore with flutter

im getting this two errors in my debug console (core_booster, getBoosterConfig = false) and (Could not reach Firestore backend.) In my firestore data i ve got a Collection "Recipes" and then in de documents i ve got each recipe with its own attribute.
Here i leave you a sneek peek of the code.
new StreamBuilder(
stream: Firestore.instance.collection('Recipes').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData)
return const Center(child: CircularProgressIndicator());
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) =>
_buildListRecipe(context, snapshot.data.documents[index]),
);
});
Then in my _buildListRecipe I'm accessing each in the value of each recipe.
new Image.network(
document["firstImage"],
width: double.infinity,
height: 150.0,
fit: BoxFit.cover,
),
did you resolve your issue and do you remember how? I reach the exact same problem, I don't found any response or tips to resolve it.
Here, a bit of me code :
void _listenToUserDatabase(String key) async {
_userStream = _usersDatabase.child(key).onValue.listen((event) {
if (event.snapshot.value != null) {
final String source = jsonEncode(event.snapshot.value);
final Map<String, dynamic> json = jsonDecode(source);
_user = UserModel.fromJson(json, key: key);
_userKey = key;
notifyListeners();
}
}, onError: (e) {
print("Listen to user database error $e");
}, onDone: () {
print("listen done");
});
}

Resources