mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-10-10 22:38:44 +02:00
fix(fs): read uncompressed Android assets from the cache copy (#3635)
In plugins/fs/android/src/main/java/FsPlugin.kt getFileDescriptor, for uncompressed assets AssetManager.openFd returns an AssetFileDescriptor whose parcel descriptor is the whole APK; its startOffset/length were dropped and Rust read from offset 0, i.e. APK bytes. Only compressed assets (openFd throws) took the cache copy path. All assets now use the cache copy path. The cache file path is also checked to stay below cacheDir/_assets. Kotlin not compiled here: unverified, needs an on-device check.
This commit is contained in:
1 parent
a934743b73
commit
f81f0447cc
2 files changed
+22
-14
No files matched your search
@@ -0,0 +1,6 @@
|
||||
---
|
||||
fs: patch
|
||||
fs-js: patch
|
||||
---
|
||||
|
||||
Fixed reading uncompressed Android assets (`$RESOURCE` files such as images or audio that are stored uncompressed in the APK) returning the bytes of the APK instead of the asset. Assets are now always read from a copy in the app cache, like compressed ones.
|
||||
@@ -44,21 +44,23 @@ class FsPlugin(private val activity: Activity): Plugin(activity) {
|
||||
|
||||
if (args.uri.startsWith(app.tauri.TAURI_ASSETS_DIRECTORY_URI)) {
|
||||
val path = args.uri.substring(app.tauri.TAURI_ASSETS_DIRECTORY_URI.length)
|
||||
try {
|
||||
val fd = activity.assets.openFd(path).parcelFileDescriptor?.detachFd()
|
||||
res.put("fd", fd)
|
||||
} catch (e: IOException) {
|
||||
// if the asset is compressed, we cannot open a file descriptor directly
|
||||
// so we copy it to the cache and get a fd from there
|
||||
// this is a lot faster than serializing the file and sending it as invoke response
|
||||
// because on the Rust side we can leverage the custom protocol IPC and read the file directly
|
||||
val cacheFile = File(activity.cacheDir, "_assets/$path")
|
||||
cacheFile.parentFile?.mkdirs()
|
||||
copyAsset(path, cacheFile)
|
||||
|
||||
val fd = ParcelFileDescriptor.open(cacheFile, ParcelFileDescriptor.parseMode(args.mode)).detachFd()
|
||||
res.put("fd", fd)
|
||||
// We cannot hand out a file descriptor of the asset itself: for uncompressed assets
|
||||
// `AssetManager.openFd` returns the descriptor of the whole APK with a start offset
|
||||
// the Rust side cannot honor, and compressed assets have no descriptor at all.
|
||||
// So we copy the asset to the cache and get a fd from there.
|
||||
// This is a lot faster than serializing the file and sending it as invoke response
|
||||
// because on the Rust side we can leverage the custom protocol IPC and read the file directly.
|
||||
val assetsCacheDir = File(activity.cacheDir, "_assets")
|
||||
val cacheFile = File(assetsCacheDir, path)
|
||||
if (!cacheFile.canonicalPath.startsWith(assetsCacheDir.canonicalPath + File.separator)) {
|
||||
invoke.reject("invalid asset path: $path")
|
||||
return
|
||||
}
|
||||
cacheFile.parentFile?.mkdirs()
|
||||
copyAsset(path, cacheFile)
|
||||
|
||||
val fd = ParcelFileDescriptor.open(cacheFile, ParcelFileDescriptor.parseMode(args.mode)).detachFd()
|
||||
res.put("fd", fd)
|
||||
} else {
|
||||
val fd = activity.contentResolver.openAssetFileDescriptor(
|
||||
Uri.parse(args.uri),
|
||||
|
||||
Reference in new issue
Block a user