yf98🌕
用心工作,用爱生活。【Expo小记】修复:使用预先准备的SqliteDB,Android真机与Expo Go正常,iOS模拟器与真机无法找到该数据库的问题:File not database.
这几天写了一个粤小词词典应用,打算做个离线版的,于是使用了自己的sqliteDB文件。
Android上一切正常,Expo Go调试正常,一到eas build iOS就文件不是数据库文件。
如果直接解析DB后缀的是没法使用的,更改一下Metro的配置,支持db文件,也可以项目使用其他的。
`
const { getDefaultConfig } = require('expo/metro-config');
const defaultConfig = getDefaultConfig(__dirname);
defaultConfig.resolver.assetExts.push('db');
module.exports = defaultConfig;
改完后,执行清理缓存的启动:
expo start -c
然后使用以下写法:
`
async function openDatabase(pathToDatabaseFile: string): Promise<SQLite.WebSQLDatabase> {
if (!(await FileSystem.getInfoAsync(FileSystem.documentDirectory + 'SQLite')).exists) {
await FileSystem.makeDirectoryAsync(FileSystem.documentDirectory + 'SQLite');
}
await FileSystem.downloadAsync(
Asset.fromModule(require(pathToDatabaseFile)).uri,
FileSystem.documentDirectory + 'SQLite/myDatabaseName.db'
);
return SQLite.openDatabase('myDatabaseName.db');
}
可以看到从资源文件里面解析出来db后,下载到本机(这里说一下:使用expo托管流的,会将资源文件托管到亚马逊的CDN上,在应用首次启动会下载下来)。
回到iOS真机上来,我使用模拟器,打开了模拟器的本地存储,发现实际上是有数据库文件的,但是似乎大小不正常,我的DB有3m,但是模拟器上下载下来的只有200kb,应该是下载的时候损坏了。所以导致不是一个db文件。于是我换了一下写法,使用了copy函数,从资源文件复制到本机,结果打包后还是不行,直接没有复制。
后来去官方论坛查看,非常多的人遇到自带db文件无法使用的问题,并且几乎没有官方人员解答,都是最后被关闭话题。其中一个是:使用hook,来监听文件下载完成后执行其他操作。这样可以避免下载问题导致的文件损坏,鉴于下载问题,我修改了一些逻辑,改成了不托管db文件,然后启动项目后从自带资源文件里复制。
`
useEffect(() => {
async function loadResourcesAndDataAsync() {
try {
SplashScreen.preventAutoHideAsync().catch((e) => console.log(e));
const getDatabase = async (databaseAsset: Asset) => {
try {
if (!(await FileSystem.getInfoAsync(sqlDir)).exists) {
await FileSystem.makeDirectoryAsync(sqlDir);
}
await FileSystem.copyAsync({
//@ts-ignore
from: databaseAsset.localUri,
to: sqlDir + '/' + databaseName,
});
return SQLite.openDatabase(databaseName);
} catch (err) { /* Handle error */
}
};
if (assets && assets[0] && !assetsError) {
const databaseAsset = assets[0];
// @ts-ignore
ZenStore.db = await getDatabase(databaseAsset);
}
} catch (e) {
// We might want to provide this error information to an error reporting service
console.warn(e);
alert(e.message);
console.error(e)
} finally {
setLoadingComplete(true);
SplashScreen.hideAsync();
}
}
loadResourcesAndDataAsync();
}, [assets]);
修改托管配置:app.json ,将db排除在外,因为我只托管图片所以将默认的*换成下面的就好了。
`
"assetBundlePatterns": [
"assets/images/*"
],
希望能帮助到遇到这个问题的小伙伴。
另外 粤小词语iOS上线啦:粤小词 Apple Store