react-native-sqlite-storage cannot open database - android

Every device we test SQLite.openDatabase on works fine except galaxy s10. I have tried every possible combination I can think of and it always just returns failed to open database. Any ideas on how to debug this? These are only a small subset of what I tried
SQLite.openDatabase(
{
name: 'my_db.db',
createFromLocation: 1,
},
() => {
console.log("OPEN DATABASE SUCCESS : ")
},
error => {
console.log("OPEN DATABASE ERROR : " + error);
}
);
in place of the 2 we tried 1, 3, 4, default, library, databases, /data/data/<app_name>/my_db.db data/data/<app_name>/my_db.sqlite
also tried in the formats like
SQLite.openDatabase({name: 'test.db', createFromLocation : path, location: 1}, this.openCB, this.errorCB);
SQLite.openDatabase("test.db", "1.0", "Test Database", 200000, this.openCB, this.errorCB);
the path was tried with ~/test.db also with
var RNFS = require('react-native-fs');
var path = RNFS.DocumentDirectoryPath + '/my_db.db';
And about 100 more things from every corner of the internet we could find. It should also be noted that
RNFS.writeFile(path, ''); works totally fine. Again works on every device and emulator except galaxy s10. What stupid thing am I missing?
EDIT:
I did an output off all the react native fs locations. /data/data wasn't an options. Which is supposed to be the correct version?
LOG CachesDirectoryPath /data/user/0/com.<app_name>/cache
LOG DocumentDirectoryPath /data/user/0/com.<app_name>/files
LOG DownloadDirectoryPath /storage/emulated/0/Download
LOG ExternalCachesDirectoryPath /storage/emulated/0/Android/data/com.<app_name>/cache
LOG ExternalDirectoryPath /storage/emulated/0/Android/data/com.<app_name>/files
LOG ExternalStorageDirectoryPath /storage/emulated/0
LOG FileProtectionKeys undefined
LOG LibraryDirectoryPath undefined
LOG MainBundlePath undefined
LOG PicturesDirectoryPath /storage/emulated/0/Pictures
LOG TemporaryDirectoryPath /data/user/0/com.<app_name>/cache
Edit2:
I added code to first create a databases folder, then if successful try touching the database file, byt writing a file with an empty string. All of which were successfuly. But the sqlite open still fails.
RNFS.mkdir(DirectoryPath).then((result) => {
console.log('Wrote folder!', result);
const dvfile = 'my_db.db';
console.log("Final db location = "+DirectoryPath+dvfile);
RNFS.writeFile(DirectoryPath+dvfile, "").then((result) => {
console.log("Was able to touch db file!?\n");
SQLite.openDatabase({name: dvfile, createFromLocation : DirectoryPath+dvfile, location: DirectoryPath+dvfile}, this.openCB, this.errorCB);
}).catch((err) => {
console.warn('Failed to touch the db file', err)
})
}).catch((err) => {
console.warn('Failed to write folder', err)
})

Try const db = SQLite.openDatabase('db.db'); with db.db in the same directory. Then, try to execute a small sql cmd.
db.transction(
(tx) => tx.executeSql("create table name;"),
(e) => console.error(e),
() => console.log("success")
);

Related

expo createfileasync sometimes throws undefined error

I have the following piece of code to download and save a file on local phone device. I have a https url for a pdf file from AWS and I am trying to download it onto android.
await FileSystem.downloadAsync(uri, fileLocation)
.then(async(u) => {
if(ext === 'pdf') {
var status = await StorageAccessFramework.requestDirectoryPermissionsAsync();
if(!status.granted) {
return;
}
await StorageAccessFramework.createFileAsync(status.directoryUri, 'receipt' , 'application/pdf')
.then (async(r) => {
const form64data = await FileSystem.readAsStringAsync(u, {encoding: FileSystem.EncodingType.Base64})
await FileSystem.writeAsStringAsync(r, form64data, {encoding: FileSystem.EncodingType.Base64});
})
.catch((e) => {
if(e === undefined) {
return Toast.error(e)
else {return Toast.error(e.data.message)}
})
}
This code downloads the file onto 2 out of 3 actual devices. On 1 out of the 3 devices I see it always goes in the catch block and throws a undefined error in the Toast. on further debugging, I found that the createFileAsync function is not working as the file is not created at all on the device. Upon opening document picker , It always asks for permissions and folder to use but then throws a undefined error which I am unable to debug.
Need suggestions to debug and therefore, fix the issue . I do not have the actual device on which it fails to be able to see logs.

Nativescript angular android app is unable to read file from private app folder after copying the file

I have a simple app in native script angular for android, where I store some user-defined data into a JSON file in the app's private folder.
It actually works, but the problem is, if I copy the file to sd card and then back in the app folder, the app can't read the content of the file. Of course, I changed the permissions of the file to 600 (that's what the original file had). But it still doesn't work.
If you ask why I'm copying the file to sd card and back it's because I'm trying to solve a problem where if I update the app in play store it is unable to read the stored JSON file created by the previous version and I think that it's somehow related.
The code for saving data into file is this:
saveUsers() {
this.adresarAppky = fs.knownFolders.currentApp();
this.adresarZrodenci = this.adresarAppky.getFolder('zrodenci');
this.zrodenciFile = this.adresarZrodenci.getFile('zrodenci.json');
this.zrodenciFile.writeText(JSON.stringify(this.users))
.then(result => {
console.log('File saved');
}).catch(err => {
console.log('Error saving ' + err);
})
}
and this is code for reading the file contents
loadSavedUsers() {
this.adresarAppky = fs.knownFolders.currentApp();
this.adresarZrodenci = this.adresarAppky.getFolder('zrodenci');
if (!File.exists(path.join(this.adresarZrodenci.path, 'zrodenci.json'))) this.saveUsers();
this.zrodenciFile = this.adresarZrodenci.getFile('zrodenci.json');
this.zrodenciFile.readText()
.then(res => {
this.zrodenciData = JSON.parse(res);
console.log('Data read ' + res);
this.users = this.zrodenciData;
this.emitSelectedUser();
}).catch(err => {
console.log('Error reading file ' + err);
});
}
The line with console.log('Error reading file') outputs this error - ReadTextTask returns no result.

Database doesn't exist/not being loaded in built app with Expo

for the last couple of months I've been working on my first app project with react native and Expo.
I'm ready to finally launch my app but I'm having one big issue: The app uses a premade sqlite database to read and update information, this database gets loaded into the app the first time it launches or if the version has been updated (via a simple variable). I tested the app with no issues via the Expo Client but, now that I'm trying it in a phone (via an apk) there's no db and I have no clue why it's not working
Here's the code that loads the db:
FileSystem.downloadAsync(
Asset.fromModule(require('../databases/programs.db')).uri,
`${FileSystem.documentDirectory}SQLite/programs-${version}.db`
).then(() => {
programsDB = SQLite.openDatabase(`programs-${version}.db`);
loadDB(loaded);
});
I have this in metro.config.js:
module.exports = {
resolver: {
blacklistRE: blacklist([/amplify\/#current-cloud-backend\/.*/]),
assetExts: ["db", "ttf", "png", "jpg"]
},
transformer: {
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: false,
},
}),
},
};
And this in app.json
"assetBundlePatterns": [
"src/library/assets/**/*",
"src/library/databases/*",
"src/library/fonts/*"
],
"packagerOpts": {
"assetExts": ["db"]
},
I've tried both with
require('../databases/programs.db'
and
require('library/databases/programs.db'
After the app tries to load stuff from the db I get the following error:
"Directory for /data/user/0/com.company.myApp/files/SQLite/programs-2020052401.db doesn't exist"
I also tried changing the source db to download from .db to .mp4 after an answer I read elsewhere but it doesn't do it either.
Any ideas? This is the last hurdle before I can finally launch my app.
SOLUTION
After tinkering with it to isolate the problem I ended up finding out that the issue was that the directory (SQLite) where the database is going to be saved in the devices wasn't being created with downloadAsync, which I would have known if I had read the docs more carefully.
I just had to make the directory first if it didn't exist and then it worked alright.
Here's how the coded ended up looking:
// Check if the directory where we are going to put the database exists
let dirInfo;
try {
dirInfo = await FileSystem.getInfoAsync(`${FileSystem.documentDirectory}SQLite`);
} catch(err) { Sentry.captureException(err) };
if (!dirInfo.exists) {
try {
await FileSystem.makeDirectoryAsync(`${FileSystem.documentDirectory}SQLite`, { intermediates: true });
} catch(err) { Sentry.captureException(err) }
};
// Downloads the db from the original file
// The db gets loaded as read only
FileSystem.downloadAsync(
Asset.fromModule(require('../databases/programs.db')).uri,
`${FileSystem.documentDirectory}SQLite/programs${version}.db`
).then(() => {
programsDB = SQLite.openDatabase(`programs${version}.db`); // We open our downloaded db
loadDB(loaded); // We load the db into the persist store
}).catch(err => Sentry.captureException(err));

Cannot open files with FileOpener2, but not getting an error in Android

I am attempting to open a PDF file with FileOpener2 (through ng-cordova) with the following code:
$cordovaFile.checkFile(cordova.file.dataDirectory, attachmentPath)
.then((fileEntry) => {
// success
fileEntry.getMetadata((metadata) => {
// metadata.size is in bytes
var megabyteSize = metadata.size / 1048576;
if (megabyteSize > 5) {
var path = cordova.file.dataDirectory + attachmentPath;
console.log(path); // prints: file:///data/data/com.ionicframework.enhatch146189/files/attachments/CS-353ES_CS-420ES_Eng.pdf which is correct
$cordovaFileOpener2.open(path, 'application/pdf').then(() => {
console.log("Opened!") // prints
}, (error) => {
console.log(error);
usePDFJs(); // tries to render PDF in app with PDFJs
});
} else {
usePDFJs();
}
})
}, function (error) {
// error
console.error(error);
});
What happens confuses me: it prompts me with an "open this file in Adobe Reader?" and lists the other PDF viewers, and the console prints "Opened!"
However, no matter what I open ANY pdf in, I get some sort of error such as "cannot open this PDF file".
Can anyone see something wrong with this code?
Apparently, if you use cordova.file.dataDirectory on android you can't open those files in other applications or attach them to emails. Silly mistake -- coded too fast and read too little on the documentation. Using cordova.file.externalApplicationStorageDirectory solved the issue.

cordova-ionic ngCordova ios or iPhone file read error code 5 ENCODING_ERR

i am using cordova-ionic framework to build app. i am new to the iOS or iPhone
in my requirement, i have to read a file in the app. i am reading file in the android app but same code showing error (code: 5).
i am following code types:
in android:
$cordovaFile.writeFile(( 'user.json', data, {'append':false} )).then(function(result) {
alert('file created.');
alert(JSON.stringify(result));
}, function(err) {
// An error occured. Show a message to the user
alert('file writed');
alert(JSON.stringify(err));
});
i can create file, writing, reading data and removing the file but in ios phone i am not able to create file using the same code.
in iPhone:
var data = {"user":{"name":"errer","email":"sdsdff#gmail.com","username":"sdfsdfsd"}};
$cordovaFile.writeFile(( 'user.json', data, {'append':false} )).then(function(result) {
// Success!
alert('file created.');
alert(JSON.stringify(result));
}, function(err) {
// An error occured. Show a message to the user
alert('file writed');
alert(JSON.stringify(err));
});
i just change my directory is cordova.file.cacheDirecotry/cordova.file.applicationDirectory
$cordovaFile.createFile(( cordova.file.cacheDirecotry+'user.json', true )).then(function(result) {
// Success!
alert('file created.');
alert(JSON.stringify(result));
}, function(err) {
// An error occured. Show a message to the user
alert('file writed');
alert(JSON.stringify(err));
});
all way getting the error like code: 12 or code: 5
please help me to solve this or give me a idea to get application file path
I have some progression.
First, I alert my cordova.file.dataDirectory or cordova.file.documentsDirectory.
They are
file:///var/mobile/...../Library/NoCloud
and
file:///var/mobile/..../Documents
Then I create a File without the prefix and succeed. Referring to this https://github.com/driftyco/ng-cordova/issues/362
and the success message shows that the native url of the file is saved in
file:///var/mobile/...../Library/files
Which is quite strange. By the way, I add the
<preference name="iosPersistentFileLocation" value="Library" />
according to https://github.com/apache/cordova-plugin-file/blob/master/doc/index.md#ios-persistent-storage-location
All the tests are running on IOS, i haven't test for Android.
Updates
All the following code worked for me and give success response
$cordovaFile.checkFile('/test.data')
$cordovaFile.createFile('test.data',false)
$cordovaFile.checkDir('/')
Hope this can solve your problems.
/*
Here is what I am using for my Android and IOS apps
Keep attention to a couple of things:
- Android and IOS have other directorynames for files
- Android devices have different root (myFSRootDirectory1 = Samsung Tab 3, msFSRootDirectory2 = Samsung SII)
- $cordovaFile functions prefixes all pathnames with root
$cordovaFileTransfer functions needs absolute pathnames
Here I create the prefixes for File functions and FileTransfer functions for Android and IOS
*/
// The $ionicPlatform and ionic.Platorm are from Ionic framework
//
$ionicPlatform.ready(function() {
if (ionic.Platform.isAndroid()) {
// If running on Android
console.log('cordova.file.externalDataDirectory: ' + cordova.file.externalDataDirectory);
//
// I use cordova.file.externalDataDirectory because this url is for Android devices
// If you remove the app from the device these url are cleared too on the device. So keep it clean.
// Remove the root from cordova.file.externalDataDirectory
//
myFsRootDirectory1 = 'file:///storage/emulated/0/'; // path for tablet
myFsRootDirectory2 = 'file:///storage/sdcard0/'; // path for phone
fileTransferDir = cordova.file.externalDataDirectory;
if (fileTransferDir.indexOf(myFsRootDirectory1) === 0) {
fileDir = fileTransferDir.replace(myFsRootDirectory1, '');
}
if (fileTransferDir.indexOf(myFsRootDirectory2) === 0) {
fileDir = fileTransferDir.replace(myFsRootDirectory2, '');
}
console.log('Android FILETRANSFERDIR: ' + fileTransferDir);
console.log('Android FILEDIR: ' + fileDir);
}
if (ionic.Platform.isIOS()) {
// if running on IOS
console.log('cordova.file.documentsDirectory: ' + cordova.file.documentsDirectory);
// I use cordova.file.documentsDirectory because this url is for IOS (NOT backed on iCloud) devices
fileTransferDir = cordova.file.documentsDirectory;
fileDir = '';
console.log('IOS FILETRANSFERDIR: ' + fileTransferDir);
console.log('IOS FILEDIR: ' + fileDir);
}
if (ionic.Platform.isAndroid() || ionic.Platform.isIOS()) {
//
// Just functions from the list below one by one ( or chain them)
//
}
});
// Download file from 'http://www.yourdomain.com/test.jpg' to test/one/test.jpg on device Filesystem
var hostPath = 'http://www.yourdomain.com/test.jpg';
var clientPath = fileTransferDir + 'test/one/test.jpg';
var fileTransferOptions = {};
$cordovaFile.downloadFile(hostPath, clientPath, true, fileTransferOptions).then (function() {
});
// Create dir test
$cordovaFile.createDir(fileDir + 'test/').then( function(dirEntry) {
});
// Create dir aganin in dir test
$cordovaFile.createDir(fileDir + 'test/one/').then( function(dirEntry) {
});
// Create empty file test.txt in test/again/
$cordovaFile.createFile(fileDir + 'test/one/test.txt', true).then( function(fileEntry) {
});
// List of files in test/again
$cordovaFile.listDir(fileDir + 'test/one/').then( function(entries) {
console.log('list dir: ', entries);
});
// Write some text into file
$cordovaFile.writeFile(fileDir + 'test/one/test.txt', 'Some text te test filewrite', '').then( function(result) {
});
// Read text written in file
$cordovaFile.readAsText(fileDir + 'test/one/test.txt').then( function(result) {
console.log('readAsText: ', result);
});
Perhaps it's because of a typo? You have cordova.file.cacheDirecotry. Shouldn't that be : cordova.file.cacheDirectory ?
Refer to the original documentation :-
https://github.com/apache/cordova-plugin-file/blob/master/doc/index.md#ios-file-system-layout
iOS has some directories as read-only. Try changing your path.
Let me know if it does not work for you.

Categories

Resources