the app works with sqlite database and it shows the data that exits in the assets very fine even though when the app closed those data is still there , the problem is when connecting with server and loading data it is saved and displayed in the app very fine but only when the app running , if the app closed every thing lost and I just found the data that already exists in assets from the beginning .
how I can save the data that loading from the server in local database even if the app is closed?
here is my database initialize function
Future<Database> initDb() async {
if (kIsWeb) {
try {
} catch (_) {}
// Set web-specific directory Here
} else {
Directory documentDirectory = await getApplicationDocumentsDirectory();
String path = join(documentDirectory.path, "data_4us.db");
// Load database from asset and copy
ByteData data = await rootBundle.load(join('data', '4us.db'));
List<int> bytes =
data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
// Save copied asset to documents
await new File(path).writeAsBytes(bytes);
var ourDb = await openDatabase(path);
return ourDb;
} }
Ok guys, I think I solve the problem
I just add this if statement to check the existing of the database
if (FileSystemEntity.typeSync(path) == FileSystemEntityType.notFound){ }
now everything is fine.
thank you .
Related
SOLVED FOR MY SITUATION. MORE INFORMATION HERE AND THEN ORIGINAL QUESTION BELOW.
===Solution===
Due to settings with Android external storage, the file_picker plugin creates a cache of the file you pick and stores it in a cache directory within the app storage location. It will not overwrite this for files with the same name on subsequent reads. So for my read/write app, the solution was to do await file.delete(); when I was done with the read operation. This ensures that the next read will then create a cached version with the updated contents
===Original Question===
I have some content in a database on a Flutter app I am using to just practice some new stuff in FLutter. I have an export button that gets this data, JSON encodes it, and writes it to a file.
If I change the content and then export a second time, I can open the file on my device and see the updated content. I also have an import button. When I press that, I use FilePicker to select a file, read the contents of the file, and then JSON decode the data into an object.
I print out the file.readAsString and see the content from the initial write.
If I manually delete the file between writes then it works. If I use file.delete() before the write, it does not work. What can I do to get the updated text when I read from the file?
Getting file to write to. (I am aware this will only work on Android as is and that's fine)
Future<File?> _getBackupDataFile(String pathToTryFirst, ExportData data) async {
Directory? directory = Directory(pathToTryFirst);
if (!await directory.exists()) directory = await getExternalStorageDirectory();
if ((await directory?.exists() ?? false) == false) {
showErrorDialog(context: context, body: "Unable to find directory to save file.");
return null;
}
return File("${directory?.path}/pm-account-backup.json");
}
Write to file as such (without the delete code):
Future<void> _writeDataToFile(ExportData data) async {
try {
File? file = await _getBackupDataFile('/storage/emulated/0/Download', data);
if(file == null) { return; }
await file.writeAsString(jsonEncode(data));
await showSuccessDialog(context: context, title: "Success", body: "${data.accounts.length} accounts backed up successfully.");
} catch (e) {
showErrorDialog(context: context, body: "Failed to write data to file.");
}
}
Simplified file pick:
FilePickerResult? result = await FilePicker.platform.pickFiles();
if (result != null) {
String path = result.files.single.path ?? '';
if((path).endsWith(".json")) {
return File(path);
}
}
Read from file as such:
String fileData = await file.readAsString();
print(fileData);
Solution for my question found after more information provided by #pskink
Due to settings with Android external storage, the file_picker plugin creates a cache of the file you pick and stores it in a cache directory within the app storage location. It will not overwrite this for files with the same name on subsequent reads. So for my read/write app, the solution was to do await file.delete(); when I was done with the read operation. This ensures that the next read will then create a cached version with the updated contents
I am currently developing a mobile app with flutter and I want to display the profile picture of a user and their friends.
The pictures are stored in Firebase Storage, but to minimize the number of requests I want to load each image once and then store it locally.
I wrote a function to get the image from Firebase storage and store it in the app document directory, but I can't figure out how to execute the function only when the file doesn't already exist locally.
This is an excerpt of my code
Future<File?> getProfilePic(String? uid) async {
Directory appDocumentsDirectory = await getApplicationDocumentsDirectory();
String filepath = "${appDocumentsDirectory.path}/profiles/$uid.jpg";
if (await File(filepath).exists()) {
return File(filepath);
} else {
var success = await downloadFromFirebaseAndSaveToLocal(
"profilepic/$uid.jpg", filepath);
if (success) {
getProfilePic(uid);
}
}
return null;
}
Somehow the condition of the if statement (await File(filepath).exists()) is always true. I guess it makes sense. I think the file exists in the directory but doesn't have any content.
Does anyone know how to check if the file has content?
A normal null check doesn't work.
Thank you for helping!
To check the size of the file, you can
if (File(filepath).lengthSync() != 0)
or
You can await the file.length()
There's some very odd problems when using flutter for MacOs apps.
I'm using the following Database initialisation:
_initDatabase() async {
Directory dbDirectory = await getApplicationDocumentsDirectory();
String path = join(dbDirectory.path, _databaseName);
//ByteData data = await rootBundle.load("assets/mydatabase.sqlite");
//List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
//await File(path).writeAsBytes(bytes);
return await openDatabase(path,
version: _databaseVersion,
//onCreate: _onCreate
);}
What is the issue?
I keep on getting error that it cannot find the table. The table absolutely exists.
But then I checked the logs and it appears it is using the /Users/myname/Documents to store the database file.
that's not what I want. The database file for this application is in the assets folder, and it should remain (when it is packaged) within the app bundle.
How do I specify the assets folder??
What am I doing wrong??
The create function, by the way, isn't working either.
Future _onCreate(Database db, int version) async {
await db.execute('''
CREATE TABLE $table (
$columnId INTEGER PRIMARY KEY,
$col1 TEXT,
$col2 TEXT,
$col3 TEXT
)
''');}
Im exhausted from trying...
I'm creating an encrypted sqflite database with sqflite_sqlcipher and would like to open it with the DB Browser for SQLCipher. For that i only need to find my .db file but I can't seem to figure out where this file is stored inside my app.
I have printed the path to the db in my init function and the output is below:
Future<Database> _initDatabase() async {
print("Database path: ${await getDatabasesPath()}");
final dbPath = await getDatabasesPath();
final path = join(dbPath, "documents.db");
final pw = await getPassword();
return await openDatabase(
path,
password: pw,
version: 1,
onCreate: _onCreate,
);
}
Database path: /data/user/0/com.example.did/databases
You could access it using Android Studio, look for Device File Manager and from there, you can access the file path.
I have a routine that copies a local SQLite database (from the Android Studio Assets folder) to the phone's document directory.
The problem I have is that this code is not very good. Sometimes the database is copied completely, and sometimes it is copied partially, or not at all. Its very buggy and I have no idea on how to improve on it.
Many times I get an error saying that certain tables cannot be found.
Here is the code that Im using:
copyDB() async
{
// Construct a file path to copy database to
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, DBAssistanceClass.databaseName);
print('The DB path is: '+ path);
// Only copy if the database doesn't exist
if (FileSystemEntity.typeSync(path) == FileSystemEntityType.notFound)
{
try
{
print('Copying DB...');
// Load database from asset and copy
ByteData data = await rootBundle.load(
join('assets', DBAssistanceClass.databaseName));
List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
// Save copied asset to documents
await File(path).writeAsBytes(bytes);
}
catch (error)
{
print(error);
}
}
}
This is for flutter, and I cannot find anything at all in dart documentation to assist.
I think if it is important to flush when you write the file. There is an Opening an asset database document in sqflite with a complete example.