How to use StreamBuilder in FirebaseStorage to inform my App from changes in my Firebase Storage? In Flutter - flutter

Here is my challenge:
I'm using the following example from https://firebase.flutter.dev/docs/storage/usage/
to upload images to my FireBaseStorage from my phone gallery (which delivers me the String filepath-variable).
Future<void> handleTaskExample2(String filePath) async {
File largeFile = File(filePath);
firebase_storage.UploadTask task = firebase_storage.FirebaseStorage.instance
.ref('uploads/picture-to-upload.jpeg')
.putFile(largeFile);
task.snapshotEvents.listen((firebase_storage.TaskSnapshot snapshot) {
print('Task state: ${snapshot.state}');
print(
'Progress: ${(snapshot.bytesTransferred / snapshot.totalBytes) * 100} %');
}, onError: (e) {
print(task.snapshot);
if (e.code == 'permission-denied') {
print('User does not have permission to upload to this reference.');
}
});
try {
await task;
print('Upload complete.');
} on firebase_core.FirebaseException catch (e) {
if (e.code == 'permission-denied') {
print('User does not have permission to upload to this reference.');
}
// ...
}
}
Actually, everything works fine. My uploaded Image to my Storage gets shown in my GridView inside the App...
But if I upload an Image to my Storage manually over the FireBase Website, my gridView (where the pictures from my storage are shown) is not auto-updating.
But if I change my screen and come back, the manually uploaded picture is shown.
It looks like I need something like a StreamBuilder that my App gets informed whenever changes happen in my Storage.
Does anyone have an Idea how to implement this or any other ideas to solve my problem?
Thanks

The listAll and list only get the data once so you unfortunately can't have a stream on them. You have 2 options here.
Call the listAll in a periodic interval like every 2-3 min
Create a cloud functions that get's triggered when files get uploaded to that specific directory and change a value in RTDB or Firestore. In the App you can listen to that data. Idealy it should be just a timestamp. You can store in your app the last timestamp you got from the database and if that changes just call listAll.
It depends on your usecase what would fit for you the best.

Related

Saving the input image from Face detection as a file? [Flutter + Google ML Kit Face Detection]

is it possible to save the processed image as a File?
Here is what I'm trying to do, our app have a KYC (Know your customer) and we implemented the
face detection to make the users do several poses. What I want is to save them as an image file and upload it on the database
Example Scenario:
App ask the user to smile > The user smiled > save the image.
Here is what I have right now:
Where the app checks if the user smiled
if (faces.isNotEmpty) {
if (inputImage.inputImageData?.size != null &&
inputImage.inputImageData?.imageRotation != null) {
if (faces[0].smilingProbability! > 0.85) {
await _getImg();
}
}
}
Then I call a Function to stop image stream then take a picture (this works but on some physical device it crashes) but if I dont stop the image stream then called the takePicture() right-away it just crashes all the time.
_getImg() async {
setState(() {
globalBusy = true;
});
await _controller.stopImageStream();
var img = await _controller.takePicture();
VerificationVarHandler.livelinesImgsPaths.add(img.path);
}
As you can see it's not the best way at least for me I think, so maybe I can use the
inputImage from the _processCameraImage() because it has a byte? then I can pass that bytes to a decoder and save it locally when I trigger a function?
Or maybe better yet there is more elegant way of achieving this?
You can check out this gfg article - https://www.geeksforgeeks.org/face-detection-in-flutter-using-firebase-ml-kit/
Learn flutter in easiest way - https://auth.geeksforgeeks.org/user/ms471841/articles

How to restrict the user from creating more than one doc in firestore database?

I have a form on my flutter app where the userr can submit his personal info:
try {
await FirebaseFirestore.instance
.collection('users')
.doc(userID).collection('personalInfo')
.add(_insertProfInfoToDBToDB.toJson());
This function is triggered by a sunmit button, now the problem is that if the user doesnt have an internet connection for example and he submit this form, then he will get an error that there is no internet connection which is coming from another function
Future<void> _tryConnection() async {
try {
final response = await InternetAddress.lookup('Example.com');
setState(() {
_isConnectionSuccessful = response.isNotEmpty;
});
} on SocketException catch (e) {
print(e);
setState(() {
_isConnectionSuccessful = false;
});
}
if (_isConnectionSuccessful != true){
Utils.showSnackBar("Please check your internet connection");
}
}
but this doesnt restric him from pressing the submit button again and again and again...
So what is happening is that once the user gets an internet connection, there will be multiple docs created at the same time inside the 'personalInfo' collection.
My question is how to restrict the user from creating more than one doc inside a collection?
Use setData
Firestore.instance.
collection('users').
document('userID').collection('collection name').document('docId')
set(data, merge: true)
Now this will create a new entry if it doesnt exist and update it if its existing
From the docs
setData(Map<String, dynamic> data, {bool merge: false}) → Future
Writes to the document referred to by this DocumentReference. If the document does not yet exist, it will be created.
.If merge is true, the provided data will be merged into an existing document instead of overwriting.>

Uploading audio to firebase flutter times out

I am trying to upload an audio file to firebase within my flutter app.
The user flow is filePicker -> confirm screen (where the user picks the details of the song like name, caption, etc). If I wait too long in the confirm screen (longer than the length of the audio file), the file "times out" and returns false for file.existsSync().
However, whenever I run through the confirm screen super fast, it works because I uploaded it before the length of the audio file finishes. I assume this has to do with caching, but I have no idea how to fix this.
My code for uploading is below:
Future<String> _uploadSongToStorage(String id, String songPath) async {
Reference ref = firebaseStorage.ref().child('songs').child(id);
//assert(songFile.existsSync());
UploadTask uploadTask = ref.putFile(File(songPath));
TaskSnapshot snap = await uploadTask;
String downloadUrl = await snap.ref.getDownloadURL();
return downloadUrl;}

How I can detect first app lauch in Flutter?

I work on a Flutter mobile app and I want to detect the first app launch to show a little tutorial to the user. I have tests the Shared-Preferences Module But when If I start the app for the first time The console tells me the key is not recognized, I think it's normal because this key does exist! There is another method for checking that?
Thank you guys
use shared preferences to store value that indicate if user has ever been in this page or not
like this
try {
final SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
splash = sharedPreferences.getString("SPLASH_DONE");
} catch (e) {
print("this is first time");
}
if (splash == null) {
page = AppSplashScreen();
} else {
page = LoginPage();
}
and after completing your first time operation call
sharedPreferences.setString("SPLASH_DONE", "DONE");

Flutter: Get information from scanned barcode number

I am quite new to Flutter, and I am currently working on an application that needs barcode reading. So I used the barcode_scan library, and I am now able to get the barcode number from a scanned barcode.
To be clear, I am not asking how to scan a barcode / get the barcode number.
My question is: how can I get more information about a product from its barcode number in Flutter (e.g. product name)? Can I do this from the barcode_scan library, or will I need something else?
Edit: Forgot to mention, when scanning QR codes I am able to get the information it encodes (e.g. product name or URL), but this is not the case with barcodes.
My current (relevant) code is as follows:
String result = 'Hey there!';
Future scanBarcode() async {
if(await Permissions.checkCameraPermission()) {
try {
await BarcodeScanner.scan().then((scan_result) {
//here scan_result is the obtained barcode number
setState(() { result = scan_result; });
});
}
//handling exceptions...
}
else {
setState(() { result = 'Camera permission denied'; });
}
}
(Side note, here Permissions.checkCameraPermission() is a function I created to check if camera permission is granted, shouldn't be relevant for the question).
I'm using the same plugin for scanning barcode or qr code for my flutter app..
String result = 'Hey there!';
Future scanBarcode() async {
if(await Permissions.checkCameraPermission()) {
try {
// I get the scan result from BarcodeScanner this way and it is working for me.
result = await BarcodeScanner.scan();
}
//handling exceptions...
}
else {
setState(() { result = 'Camera permission denied'; });
}
}
Well, it seems the only plausible way to do it from Flutter would be to use a barcode lookup API like #RichardHeap proposed in the comments. If my app was Flutter only (without a backend server connected to it) I believe I would have gone that way.
But I guess I'll just send the barcode number itself to the backend and deal with it on the server-side.
What I understand is, on scanning the code, you need the information / data about the product.
If I understood it right, there are several aggregators of the barcode. You can get APIs from them. But there is not single place from where you get all the information.