【Expo小记】修复:使用预先准备的SqliteDB,Android真机与Expo Go正常,iOS模拟器与真机无法找到该数据库的问题:File not database. 发表于 2022-08-24 更新于 2022-09-24
广州
开发 ReactNative Expo 【Expo小记】修复:使用预先准备的SqliteDB,Android真机与Expo Go正常,iOS模拟器与真机无法找到该数据库的问题:File not database. ❄️2winter 2022-08-24 2022-09-24 这几天写了一个粤小词词典应用,打算做个离线版的,于是使用了自己的sqliteDB文件。
Android上一切正常,Expo Go调试正常,一到eas build iOS就文件不是数据库文件。
如果直接解析DB后缀的是没法使用的,更改一下Metro的配置,支持db文件,也可以项目使用其他的。
`
1 2 3 4 5 6 7 const { getDefaultConfig } = require ('expo/metro-config' );const defaultConfig = getDefaultConfig (__dirname);defaultConfig.resolver .assetExts .push ('db' ); module .exports = defaultConfig;
改完后,执行清理缓存的启动:
expo start -c
然后使用以下写法:
`
1 2 3 4 5 6 7 8 9 10 11 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文件,然后启动项目后从自带资源文件里复制。
`
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 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 ({ from : databaseAsset.localUri , to : sqlDir + '/' + databaseName, }); return SQLite .openDatabase (databaseName); } catch (err) { } }; if (assets && assets[0 ] && !assetsError) { const databaseAsset = assets[0 ]; ZenStore .db = await getDatabase (databaseAsset); } } catch (e) { console .warn (e); alert (e.message ); console .error (e) } finally { setLoadingComplete (true ); SplashScreen .hideAsync (); } } loadResourcesAndDataAsync (); }, [assets]);
修改托管配置:app.json ,将db排除在外,因为我只托管图片所以将默认的*换成下面的就好了。
`
1 2 3 "assetBundlePatterns": [ "assets/images/*" ],
希望能帮助到遇到这个问题的小伙伴。
另外 粤小词语iOS上线啦:粤小词 Apple Store