Flutter - SQFlite store and load image from database - android

I want to save an image inside the sqflite database and the later on, I want to display it in a SliverAppBar as a background. Till now I am able to save the image(not sure if it is right, but throws no error XD):
Directory directory = await getApplicationDocumentsDirectory();
String path = directory.path;
File newImage = await _image.copy('$path/${recipeName.text}.png'); //_image already taken with image_picker plugin
String base64Encoded = base64Encode(newImage.readAsBytesSync());
And this String I am saving inside the database. But I also want to display. And as far I know, I have to get the String, but from now I on, I do not know anything how to get further. I have written a function to get the String, but do not know what I should do with this String. The function looks like this:
Future fetchRecipe(String name) async{
var dbHelper = new DBHelper();
Future<List<Recipes>> recipes = dbHelper.getSpecRecipe(name);
return recipes;
}
The getSpecRecipe(name) points to this function:
Future<List<Recipes>> getSpecRecipe(String recipeName) async{
List<Map> list = await _db.rawQuery("SELECT * FROM recipes WHERE name = ?", [recipeName]);
List<Recipes> recipes = new List();
for(int i =0; i < list.length; i++){
recipes.add(new Recipes(list[i]["id"], list[i]["name"], list[i]["definition"], list[i]["duration"], list[i]["favorite"], list[i]["timestamp"], list[i]["image"], list[i]["backgroundColor"]));
}
return recipes;
}
It would be awesome, if somebody would be able to solve my problem. Thanks in advanceXD

From the snippets provided, it seems that you're trying to save the image as a base64 on your database. And as mentioned by #Nordeast in the comments, it's better to save the image on the device's storage and store the file path instead. Also, given the snippets provided, it's difficult to replicate the behavior locally.

Related

Flutter: How can I update a CSV cell?

I am creating a language app and the class material is stored in a CSV. So far I can read a specific cell from the CSV but I don't know how to update a specific cell and I can't find anything online on how to accomplish that. How can I code that?
I am using the csv package from pub.dev. This is how I am reading from the csv:
readCSV(row, col) async {
var csvFILE = await rootBundle.loadString("assets/class01.csv");
List<List<dynamic>> csvDATA = CsvToListConverter().convert(csvFILE);
setState(() {
displayText = csvDATA[row][col];
});
}

List.contains returns false even though object's all variables are same

On a project i am working on i list all contacts with checkboxlist. When you tap one it adds to selectedContact list and Database, tap again and it deletes from both so far so good. My problem was when app restarts selected Contacts also zeroed so i used database. I save phone numbers and query all contacts with that phone number and keep adding it to selectedContacts. The problem is even though selectedContact items has the same values as _contacts items selectedContact.contains(c) returns false.
Any ideas?
c is the 'Contact' class object
return ListView.builder(
itemCount: _contacts?.length ?? 0,
itemBuilder: (BuildContext context, int index) {
Contact c = _contacts?.elementAt(index);
//print(snapshot.data[index]);
//selectedContacts.forEach((element) {print(element.phones.first.value);});
//print(selectedContacts.contains(c).toString() +" " +c.phones.first.value);
return CheckboxListTile(
value: selectedContacts.contains(c),
onChanged: (bool value) {
setState(() {
value
? addDb(c)
: deleteDb(c);
});
},
title: Text(c.displayName ?? ""),
secondary: CircleAvatar(child: Text(c.initials())),
);
void addDb(Contact c) {
selectedContacts.add(c);
DatabaseHelper.addContact(c);
}
void deleteDb(Contact c) {
selectedContacts.remove(c);
DatabaseHelper.deleteContact(c);
}
var selectedContacts = List<Contact>();
void importFromDatabase()async{
var import = await DatabaseHelper.importContacts();
import.forEach((element)async {
var contacts = (await ContactsService.getContactsForPhone(element,withThumbnails: false,iOSLocalizedLabels: true)).toList();
selectedContacts.addAll(contacts);
});
}
I have some kind of debugging print statement below which prints selectedContacts and prints if it contains the C
but even though their variables are same it returns false.
EDIT:
Contact class is from contacts_service package
// Name
String displayName, givenName, middleName, prefix, suffix, familyName;
// Company
String company, jobTitle;
// Email addresses
Iterable<Item> emails = [];
// Phone numbers
Iterable<Item> phones = [];
// Post addresses
Iterable<PostalAddress> postalAddresses = [];
// Contact avatar/thumbnail
Uint8List avatar;
List.contains checks the items in the list for strict equality. The Contact class from the referenced package defines equality as two objects having equal values in 16 different fields. If even one of them is different in the object you are checking with, contains will return false. Since you are only saving phone numbers in your database, you are probably not saving all the fields that a Contact object has, so when you recreate that object, it won't "equal" the object it originally referred to.
You need to store the whole object in your database. Relational databases aren't ideal for storing objects with a complex structure, so instead I would recommend using a NoSQL database such as hive, which comes with the added bonus of being able to operate exponentially faster than sqflite due to its use of a memory buffer.
Fortunately, the Contact class defines toMap and fromMap methods, so both storage and retrieval are easy:
// Storage
var box = Hive.box('contactsBox');
var payload = contact.toMap();
await box.put(contact.phones.first, payload);
// Retrieval
var box = Hive.box('contactsBox');
var stored = box.get(phoneNumber);
var contact = Contact.fromMap(stored);
(Note: box.put returns a future, but awaiting it isn't strictly necessary. Storage of data into the memory buffer is synchronous and the future only resolves when the data is successfully written to the file storage. If you don't care about waiting for that to happen and want to access the data immediately, you can skip the await here.)

Can't extract cities of country OpenWeather

I wanna use open-weather API for my application. for that i thought i might be able to save cities and their IDs in my own app in a json file and whenever i user wants a locations weather, app selects city's ID from json and make API call.
for that i downloaded a 30MB Json file provided by Openweather, it contains all countries and all theirs cities. putting a 30MB in my app isn't a good idea apparently. so i decided to extract my country cities only. but the point is, this idea could not be done. so many cities from different countries has same names. and extracted json was huge again. even some coutry codes are cities in other countries.
i wonder if there is a way better implementation. or any idea or way to extract just cities of a country.
any help to implement weather call in my app for different cities would be appreciated
I know this question is old but I recently bumped into this problem too. The way I ended up doing it was making city.list.json in to a default exported JSON object and writing a node script to then strip cities out by country code:
var fs = require('fs');
var cityList = require('./city.list.js');
let output = {};
let countryCodes = [];
cityList.forEach((city) => {
const country = city.country;
if (country) {
if (!countryCodes.includes(country)) {
countryCodes.push(country);
}
if (!output[country]) {
output[country] = [];
}
output[country].push({
id: city.id,
name: city.name,
});
}
});
for (const [key, value] of Object.entries(output)) {
const fileName = 'city.' + key.toLowerCase() + '.json';
fs.writeFile(fileName, JSON.stringify(value), function (err) {
if (err) console.error(err.message);
console.log(fileName + ' - saved!');
});
}
fs.writeFile('countrycodes.json', JSON.stringify(countryCodes), function (err) {
if (err) console.error(err.message);
console.log('countrycodes.json' + ' - saved!');
});
This totally worked! Only problem I then ran into is city.list.json includes country names, and they are not differentiated in the data...

Add a lot of images dynamically to SQLite Database Android

I hope you are good.
I'm developping an application that has to retrieve images from sqlite database, for each row I have one image (using obviously blob as a type), and I was wondering if I could not only add one image but a lot, without knowing how much images the user wants to add, for example: User1 wants to add 3 images to database. User2 5 images and so on. How can I store them? is there a kind of Blob[] or something? And if possible how can I choose more than one image from galery?
I'm not used to make posts in english so I hope I explained well ^^'.
Thank you.
Save the images in a list as base64 strings like:
String img1 = Base64.encode(value_of_image, Base64.DEFAULT);
.
.
.
String img25 = Base64.encode(value_of_image, Base64.DEFAULT);
List<String> imagesListActivity = new ArrayList();
imagesList.add(img1);
.
.
.
imagesList.add(img25);
and in your save method in helper class, you can do sth like:
public void saveImageList(List<String> images){
ContentValues cv = new ContentValues();
for(int i = 0; i < images.length; i++){
cv.put(COL_NAME, images[i);
}
}
and in activity class, try this by passing the actual list like below:
DBHelper dbHelper = new DBHelper();
dbHelper.saveImageList(imagesList);

Where is stored the database retrieved by context.getDatabasePath("db1").getAbsolutePath()

I need to delete all the databases stored in the database space of the application. I stored them using this path: context.getDatabasePath("db1").getAbsolutePath()
I have a lot of databases, with random names, so i dont know al the names, i just want to delete all of them.
I tryed with this:
String filesDir = ApplicationContextProvider.getContext().getFilesDir().getAbsolutePath();
File cache = new File(filesDir);
if (cache.isDirectory()) {
String[] children = cache.list();
for (int i = 0; i < children.length; i++) {
System.out.println("Deleting: "+children[i]);
new File(cache, children[i]).delete();
}
}
But it doesn't works. The databases are still there.
You don't need to know that path. Just use the list of databases you can get to delete them.
for (String databaseName : context.databaseList()) {
context.deleteDatabase(databaseName);
}
If you really need it
File databasesPath = context.getDatabasePath("ignored").getParentFile();
The path you get via getFilesDir is a different one.

Categories

Resources