How to use Multi Image picker with Flutter Image Compress? - firebase

I have successfully implemented flutter multi image picker. But I want to reduce its quality. I have seen threads where its been said to use flutter_Image_compress library. But I can't seem to understand that how to implement it with multi image picker.
Multi Image picker
Future<List<Asset>> loadAssets() async {
List<Asset> resultList = List<Asset>();
String error = "No error Detected";
try {
resultList = await MultiImagePicker.pickImages(
maxImages: 10,
enableCamera: true,
selectedAssets: images,
cupertinoOptions: CupertinoOptions(takePhotoIcon: "chat"),
materialOptions: MaterialOptions(
actionBarColor: "#abcdef",
actionBarTitle: "Upload Image",
allViewTitle: "All Photos",
useDetailsView: false,
selectCircleStrokeColor: "#000000",
),
);
showInSnackBar("loading images");
print(resultList.length);
print((await resultList[0].getThumbByteData(122, 100)));
print((await resultList[0].getByteData()));
print((await resultList[0].metadata));
print("loadAssets is called");
} on Exception catch (e) {
error = e.toString();
print(error);
}
if (!mounted){
print("Not mounted");
}
else {
setState(() {
images = resultList;
_error = error;
});
}
return images;
}
Flutter image compress
void compressImage(File file) async {
final filePath = file.absolute.path;
final lastIndex = filePath.lastIndexOf(new RegExp(r'.jp'));
final splitted = filePath.substring(0, (lastIndex));
final outPath = "${splitted}_out${filePath.substring(lastIndex)}";
final compressedImage = await FlutterImageCompress.compressAndGetFile(
filePath,
outPath,
minWidth: 1000,
minHeight: 1000,
quality: 70);
}
This is what i did
Future<List<Asset>> loadAssets() async {
List<Asset> resultList = List<Asset>();
List<File> fileImageArray=[];
String error = "No error Detected";
try {
resultList = await MultiImagePicker.pickImages(
maxImages: 10,
enableCamera: true,
selectedAssets: images,
cupertinoOptions: CupertinoOptions(takePhotoIcon: "chat"),
materialOptions: MaterialOptions(
actionBarColor: "#abcdef",
actionBarTitle: "Upload Image",
allViewTitle: "All Photos",
useDetailsView: false,
selectCircleStrokeColor: "#000000",
),
);
resultList.forEach((imageAsset) async {
final filePath = await FlutterAbsolutePath.getAbsolutePath(imageAsset.identifier);
File tempFile = File(filePath);
if (tempFile.existsSync()) {
fileImageArray.add(tempFile);
}
});
compressImage(fileImageArray);
showInSnackBar("loading images");
print(resultList.length);
print((await resultList[0].getThumbByteData(122, 100)));
print((await resultList[0].getByteData()));
print((await resultList[0].metadata));
print("loadAssets is called");
} on Exception catch (e) {
error = e.toString();
print(error);
}
if (!mounted){
print("Not mounted");
}
else {
setState(() {
print('Presed1');
images = resultList;
_error = error;
});
}
return images;
}
void compressImage(fileImageArray) async {
for(var i in fileImageArray){
final filePath = i.absolute.path;
final lastIndex = i.lastIndexOf(new RegExp(r'.jp'));
final splitted = i.substring(0, (lastIndex));
final outPath = "${splitted}_out${filePath.substring(lastIndex)}";
final compressedImage = await FlutterImageCompress.compressAndGetFile(
filePath,
outPath,
minWidth: 240,
minHeight: 240,
quality: 5);
setState(() {
print('pressed2');
fileImageArray= compressedImage;
});
}
}
onPressed: () async {
List<Asset> asst = await loadAssets();
if (asst.length == 0) {
showAlert("No images selected");
}
SizedBox(height: 10,);
showInSnackBar('Images Successfully loaded');
// SnackBar snackbar = SnackBar(content: Text('Please wait, we are uploading'));
//_scaffoldKey.currentState.showSnackBar(new SnackBar(content: new Text(value)));
}

Please use this to convert List to List
List<File> fileImageArray=[];
...
resultList.forEach((imageAsset) async {
final filePath = await FlutterAbsolutePath.getAbsolutePath(imageAsset.identifier);
File tempFile = File(filePath);
if (tempFile.existsSync()) {
fileImageArray.add(tempFile);
}
});
Give fileImageArray to compressImage method.
and iterate it using for loop
void compressImage(fileImageArray) async {
for(var i in fileImageArray){
final filePath = i.absolute.path;
final lastIndex = i.lastIndexOf(new RegExp(r'.jp'));
final splitted = i.substring(0, (lastIndex));
final outPath = "${splitted}_out${filePath.substring(lastIndex)}";
final compressedImage = await FlutterImageCompress.compressAndGetFile(
filePath,
outPath,
minWidth: 240,
minHeight: 240,
quality: 5);
setState(() {
fileImageArray= compressedImage;
});
}
}

Flutter Absolute Path is not in development anymore and is not updated with the android v2 embedding. Hence I suggest to use path_provider in the below to transform an Asset to File and compress:
import 'package:multi_image_picker/multi_image_picker.dart';
import 'package:path_provider/path_provider.dart';
Future<File> compressAndUploadAssetImage(Asset asset, Reference ref) async {
final byteData = await asset.getByteData();
final tempFile = File("${(await getTemporaryDirectory()).path}/${asset.name}");
final file = await tempFile.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes),);
File compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 70);
return compressedFile;
}

Related

Flutter async await not working as expected. how execute a function after anthor function has executing completely?

I am facing an issue related to Flutter async-await. I created Future<void> uploadAddAuctionSelectImages()
Which upload selected user pictures to firestore and add the pictures Url in List<String> selectedPicturesUrlList = [];
and void addAuction()
function which supposed to set auction data inculding the selected pictures to the firestore database as a new auction. the problem here is that the addAuction
function executed before the completed exeutetion of Future<void> uploadAddAuctionSelectImages() function So, in the first time the addAuction is called the selectedPicturesUrlList is already empty because uploadAddAuctionSelectImages is not executed yet. so how can I solve this problem (how can I execute addAuction after uploadAddAuctionSelectImagescomplete execution).
it's is uploadAddAuctionSelectImages function :
Future<void> uploadAddAuctionSelectImages() async {
print("LIST Length before upload picture ${selectedPicturesUrlList.length}");
emit(uploadAddAuctionSelectImagesLoadingState());
if (AddAuctionSelectedImagesList!.length < 1)
print("There is no picture selected");
for(int element=0;element<AddAuctionSelectedImagesList!.length;element++) {
await firebase_storage.FirebaseStorage.instance
.ref()
.child(
'Auctions pictures/${Uri.file(AddAuctionSelectedImagesList![element].path).pathSegments.last}')
.putData(await AddAuctionSelectedImagesList![element].readAsBytes())
.then((p0) {
p0.ref.getDownloadURL().then((value) {
selectedPicturesUrlList.add(value.toString());
print("LIST Length after upload picture ${selectedPicturesUrlList.length}");
print("Select pictures----------> ${value}");
emit(uploadAddAuctionSelectImagesSuccessState());
}).catchError((error) {
print(
"error when uploading selected picture to fireStorage ${error.toString()}");
emit(uploadAddAuctionSelectImagesErrorState());
});
}).catchError((error) {
print(
"error when uploading selected picture to fireStorage ${error.toString()}");
emit(uploadAddAuctionSelectImagesErrorState());
});
}
}
addAuction Function :
void addAuction({
required Product_Model product_model,
required isLive,
auc_end_date,
auc_start_date,
auc_hours_left,
isAuctionEnded,
}) {
print("add auction function executing");
emit(AddAuctionLoadingState());
AuctionModel model = AuctionModel(
product_model: product_model,
auc_is_live: isLive,
auc_start_date: auc_start_date,
auc_seller: "${userDate!.firstName} ${userDate!.lastName}",
auc_is_end: isAuctionEnded,
auc_hours_left: auc_hours_left,
auc_end_date: auc_end_date,
);
FirebaseFirestore.instance
.collection("auctions")
.add(model.toJson())
.then((value) {
print("Auction added successfully");
selectedPicturesUrlList.clear();
emit(AddAuctionSuccessState());
}).catchError((error) {
print("Auction added Error ${error.toString()}");
emit(AddAuctionErrorState());
}).catchError((error) {
print("Auction added Error ${error.toString()}");
});
}
calling the both functions :
function: () async {
if (cubit.AddAuctionSelectedImagesList!.length == 0 ||
cubit.AddAuctionSelectedImagesList!.length > 6) {
IsUpload=false;
Fluttertoast.showToast(
msg: "upload at lest 1 picture and at most 6",
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
}
else
IsUpload=true;
if (formKey.currentState!.validate() &&
(IsUpload)) {
await cubit.uploadAddAuctionSelectImages().then((value)
=> cubit.addAuction(
product_model: Product_Model(
pro_Description: descriptionController.text,
pro_title: titleController.text,
pro_start_price: int.parse(initialPriceController.text),
pro_reverse_price: int.parse(ReversePriceController.text),
pro_brand: brandController.text,
pro_category: cubit.selectedCategoryValue,
pro_image1: cubit.selectedPicturesUrlList[0],
pro_image2: cubit.selectedPicturesUrlList.length>=2? cubit.selectedPicturesUrlList[1]: "",
pro_image3: cubit.selectedPicturesUrlList.length>=3? cubit.selectedPicturesUrlList[2]: "",
pro_image4: cubit.selectedPicturesUrlList.length>=4? cubit.selectedPicturesUrlList[3]: "",
pro_image5: cubit.selectedPicturesUrlList.length>=5? cubit.selectedPicturesUrlList[4]: "",
pro_image6: cubit.selectedPicturesUrlList.length>=6? cubit.selectedPicturesUrlList[5]: "",
),
isLive: cubit.selectedAuctionType=="Live"?true:false,
auc_hours_left: AuctionHoursController.text,
auc_start_date: DateTime.now().toString(),
auc_end_date: "",
isAuctionEnded: false,
)
);
}

Data is not being read from firebase Realtime Database using a Stream in Flutter

since Firebase was updated I have been having some issues, first it was because now, instead of a map, an Object? is returned and that is now fixed, but I can't seem to get any data from the database. I can put it there fine but the reading is not working.
This is on my firebase_utils .dart file
FirebaseDatabase data = FirebaseDatabase.instance;
DatabaseReference database = data.ref();
Future<void> init() async {
FirebaseAuth.instance.userChanges().listen((user) {
if (user != null) {
//_loginState = ApplicationLoginState.loggedIn;
} else {
//_loginState = ApplicationLoginState.loggedOut;
}
});
if (!kIsWeb) {
data.setPersistenceEnabled(true);
data.setPersistenceCacheSizeBytes(10000000);
}
}
I have this class:
class ReservationStreamPublisher {
Stream<List<Reservation>> getReservationStream() {
final stream = database.child('reservations').onValue;
final streamToPublish = stream
.map((event) {
List<Reservation> reservationList = [];
Map<String, dynamic>.from(event.snapshot.value as dynamic)
.forEach((key, value) => reservationList.add(Reservation.fromRTDB(value)));
print(reservationList);
return reservationList;
});
return streamToPublish;
}
}
Next is my Reservation.fromRTDB
factory Reservation.fromRTDB(Map<String, dynamic> data) {
return Reservation(
pin: data['pin'],
day: data['day'],
hour: data['hour'],
duration: data['duration'],
state: data['state'],
userEmail: data['client_email'],
completed: data['completed'],
id: data['id'],
dateMade: '',
timeMade: '');
}
And this is one of the places where I am supposed to show data
Text('Slots Reservados neste dia:'),
_selectedDate != null
? StreamBuilder(
stream:
ReservationStreamPublisher().getReservationStream(),
builder: (context, snapshot) {
final tilesList = <ListTile>[];
if (snapshot.hasData) {
List reservations =
snapshot.data as List<Reservation>;
int i = 0;
do {
if (reservations.isNotEmpty) {
if (reservations[i].day !=
(DateFormat('dd/MM/yyyy')
.format(_selectedDate!))) {
reservations.removeAt(i);
i = i;
} else
i++;
}
} while (i < reservations.length);
try {
tilesList
.addAll(reservations.map((nextReservation) {
return ListTile(
leading: Icon(Icons.lock_clock),
title: Text(
"Das ${nextReservation.hour} as ${nextReservation.duration}"),
);
}));
} catch (e) {
return Text(
'Ainda nao existem reservas neste dia');
}
}
// }
if (tilesList.isNotEmpty) {
return Expanded(
child: ListView(
children: tilesList,
),
);
}
return Text('Ainda nao existem reservas neste dia');
})
: SizedBox(),
I am not getting any error at the moment, but no data is returned.This is a Reservation example on my RTDB

Update Firebase with the final score and display to user

I'm getting the score and topicTotal from the state and printing them, however, I want to update Firebase with the topicTotal by retrieving topicTotal in report. Every way I try to access topicTotal in report, I get null in Firebase or The getter 'topicTotal' was called on null.
How can I access topicTotal in report and update Firebase with it? Also, how can I display topicTotal to the user?
set score(Options newValue) {
var score = idx += newValue.score;
_score = newValue;
print(score);
_score = newValue;
notifyListeners();
}
set topicTotal(Options newValue) {
var topicTotal = idx;
_score = newValue;
this._topicTotal = newValue;
print(topicTotal);
notifyListeners();
}
model
class Report {
...
int topicTotal;
Report({ this.uid, this.topics, this.email, this.total, this.topicTotal, this.level, this.id, this.title, this.description, this.img });
factory Report.fromMap(Map data) {
return Report(
uid: data['uid'],
email: data['email'],
total: data['total'] ?? 0,
topics: data['topics'] ?? {},
topicTotal: data['topicTotal'] ?? 34,
level: data['level'] ?? 383,
id: data['id'] ?? '',
title: data['title'] ?? '',
description: data['description'] ?? '',
img: data['img'] ?? 'default.png',
);
}
}
Here I can access total but not topicTotal
if (report != null)
Text('${report.total ?? 0}',
style: Theme.of(context).textTheme.display3),
Text('Assessments Completed',
style: Theme.of(context).textTheme.subhead),
Spacer(),
if (report != null)
Text('your topic score is ${report.topicTotal ?? 0}'),
onPressed: () {
_updateUserReportWithTopics(assessment, state, optionSelected);
Future<void> _updateUserReportWithTopics(Assessment assessment, AssessmentState state, Options optionSelected) {
state.topicTotal = optionSelected;
return Global.reportRef.upsert(
({
'total': FieldValue.increment(1),
'topics': {
'${assessment.topic}': FieldValue.arrayUnion([
assessment.title,
assessment.topicTotal,
assessment.questions.length,
]),
},
//'topicTotal': state.topicTotal = optionSelected
}),
);
}

Flutter Firebase if document doesn't exist

I just want to say if the document exists setState(the first one) else setState(the second one). I'm new in flutter so please don't hate :)
Thanks for helping!
Future<String> TerminBesetztOderFrei(String Friseur, String Tag, String Uhrzeit) async {
await Firestore.instance.collection("$Friseur/1/$Tag/1/$Uhrzeit")
.getDocuments()
.then((querySnapshot) {
querySnapshot.documents.forEach((result) {
print(result.exists);
setState(() {
terminText = "Termin nicht verfügbar!";
terminTextFarbe = Colors.red;
buttonVisible = false;
});
});
});
setState(() {
if(nameController.text != "" && telController.text != "") {
terminText = "Termin verfügbar!";
terminTextFarbe = Colors.green;
buttonVisible = true;
} else {
terminText = "Termin verfügbar! Bitte Name und Telefon eingeben!";
terminTextFarbe = Colors.green;
buttonVisible = false;
}
});
}
If you have the document Id:
final docSnapshot = await Firestore.instance
.collection("$Friseur/1/$Tag/1/$Uhrzeit")
.document(${doc_id_here})
.get();
if(docSnapshot.exists) {
setState(...)
}
else {
setState(...)
}
If you haven't
final querySnapshot = await Firestore.instance
.collection("$Friseur/1/$Tag/1/$Uhrzeit")
.getDocuments();
if(querySnapshot.documents.isNotEmpty) {
setState(...)
}

Unable to store image url in Firestore

I successfully uploaded the image to firebase storage but I'm having trouble to store image url in firestore.
I received an error on console when trying to view the image:
core.js:6462 WARNING: sanitizing unsafe URL value
C:\fakepath\coke.jpg (see http://g.co/ng/security#xss)
GET unsafe:C:\fakepath\coke.jpg net::ERR_UNKNOWN_URL_SCHEME
Below is the html code: (details.page.html)
<!-- PRODUCT PICTURE INPUT -->
<ion-item>
<ion-label position="stacked">Product Picture</ion-label>
<ion-input accept="image/*" type="file" name="productPics" formControlName="productPics" (change)="showPreview($event)"></ion-input>
</ion-item>
Below is the typescript code: (details.page.ts)
ngOnInit() {
this.productForm = this.fb.group({
productPics: new FormControl('', Validators.compose([
Validators.required,
])),
});
this.resetForm();
}
showPreview(event: any) {
if (event.target.files && event.target.files[0]) {
const reader = new FileReader();
reader.onload = (e: any) => this.imgSrc = e.target.result;
reader.readAsDataURL(event.target.files[0]);
this.selectedImage = event.target.files[0];
} else {
this.imgSrc = "./assets/default_image.jpg";
this.selectedImage = null;
}
}
async saveProduct(formValue) {
this.isSubmitted = true;
this.product.userId = this.authService.getAuth().currentUser.uid;
if (this.productId) {
try {
this.product.createdAt = new Date().getTime();
console.log('product add');
console.log(this.productForm.value);
var filePath = `${formValue.productCategory}/${this.selectedImage.name}${new Date().getTime()}`;
const fileRef = this.storage.ref(filePath);
this.storage.upload(filePath, this.selectedImage).snapshotChanges().pipe(
finalize(() => {
fileRef.getDownloadURL().subscribe((url) => {
formValue['productPics'] = url;
this.service.insertImageDetails(formValue);
this.resetForm();
})
})
).subscribe();
await this.productService.addProduct(this.product);
await this.loading.dismiss();
this.navCtrl.navigateBack('/vendor-tabs/home-vendor');
} catch (error) {
console.log('product dont add');
this.presentToast('Error trying to save');
}
}
}
Below is the service: (product.service.ts)
private productsCollection: AngularFirestoreCollection<Product>;
addProduct(product: Product) {
return this.productsCollection.add(product);
}
getProduct(id: string) {
return this.productsCollection.doc<Product>(id).valueChanges();
}
updateProduct(id: string, product: Product) {
return this.productsCollection.doc<Product>(id).update(product);
}
deleteProduct(id: string) {
return this.productsCollection.doc(id).delete();
}
insertImageDetails(image) {
this.productsCollection.add(image);
}

Resources