Skip to content

Commit c5af551

Browse files
JSKittyclaude
andcommitted
fix: Android file_message crash when sending marketplace Mini Apps
Mini Apps installed from the marketplace are stored as regular file paths in the app's data directory, not as content:// URIs. The Android code was always trying to use ContentResolver which crashes on regular file paths. Now detects whether the path is a content:// URI or a regular file path and uses the appropriate method to read the file. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent cdc3679 commit c5af551

1 file changed

Lines changed: 72 additions & 14 deletions

File tree

src-tauri/src/message.rs

Lines changed: 72 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,16 +1876,16 @@ pub async fn file_message(receiver: String, replied_to: String, file_path: Strin
18761876
#[cfg(not(target_os = "android"))]
18771877
{
18781878
let path = std::path::Path::new(&file_path);
1879-
1879+
18801880
// Check if file exists first
18811881
if !path.exists() {
18821882
return Err(format!("File does not exist: {}", file_path));
18831883
}
1884-
1884+
18851885
// Read file bytes
18861886
let bytes = std::fs::read(&file_path)
18871887
.map_err(|e| format!("Failed to read file: {}", e))?;
1888-
1888+
18891889
// Check if file is empty
18901890
if bytes.is_empty() {
18911891
return Err(format!("File is empty (0 bytes): {}", file_path));
@@ -1912,19 +1912,48 @@ pub async fn file_message(receiver: String, replied_to: String, file_path: Strin
19121912
let bytes = cached_bytes.clone();
19131913
let extension = ext.clone();
19141914
drop(cache);
1915-
1915+
19161916
// Clear the cache after use
19171917
ANDROID_FILE_CACHE.lock().unwrap().remove(&file_path);
1918-
1918+
19191919
AttachmentFile {
19201920
bytes,
19211921
img_meta: None,
19221922
extension,
19231923
}
19241924
} else {
19251925
drop(cache);
1926-
// Fall back to reading directly (may fail if permission expired)
1927-
filesystem::read_android_uri(file_path)?
1926+
// Check if this is a content:// URI or a regular file path
1927+
if file_path.starts_with("content://") {
1928+
// Content URI - use Android ContentResolver
1929+
filesystem::read_android_uri(file_path)?
1930+
} else {
1931+
// Regular file path (e.g., marketplace apps) - use standard file I/O
1932+
let path = std::path::Path::new(&file_path);
1933+
1934+
if !path.exists() {
1935+
return Err(format!("File does not exist: {}", file_path));
1936+
}
1937+
1938+
let bytes = std::fs::read(&file_path)
1939+
.map_err(|e| format!("Failed to read file: {}", e))?;
1940+
1941+
if bytes.is_empty() {
1942+
return Err(format!("File is empty (0 bytes): {}", file_path));
1943+
}
1944+
1945+
let extension = file_path
1946+
.rsplit('.')
1947+
.next()
1948+
.unwrap_or("bin")
1949+
.to_lowercase();
1950+
1951+
AttachmentFile {
1952+
bytes,
1953+
img_meta: None,
1954+
extension,
1955+
}
1956+
}
19281957
}
19291958
}
19301959
};
@@ -2353,16 +2382,16 @@ pub async fn file_message_compressed(receiver: String, replied_to: String, file_
23532382
#[cfg(not(target_os = "android"))]
23542383
{
23552384
let path = std::path::Path::new(&file_path);
2356-
2385+
23572386
// Check if file exists first
23582387
if !path.exists() {
23592388
return Err(format!("File does not exist: {}", file_path));
23602389
}
2361-
2390+
23622391
// Read file bytes
23632392
let bytes = std::fs::read(&file_path)
23642393
.map_err(|e| format!("Failed to read file: {}", e))?;
2365-
2394+
23662395
// Check if file is empty
23672396
if bytes.is_empty() {
23682397
return Err(format!("File is empty (0 bytes): {}", file_path));
@@ -2389,19 +2418,48 @@ pub async fn file_message_compressed(receiver: String, replied_to: String, file_
23892418
let bytes = cached_bytes.clone();
23902419
let extension = ext.clone();
23912420
drop(cache);
2392-
2421+
23932422
// Clear the cache after use
23942423
ANDROID_FILE_CACHE.lock().unwrap().remove(&file_path);
2395-
2424+
23962425
AttachmentFile {
23972426
bytes,
23982427
img_meta: None,
23992428
extension,
24002429
}
24012430
} else {
24022431
drop(cache);
2403-
// Fall back to reading directly (may fail if permission expired)
2404-
filesystem::read_android_uri(file_path)?
2432+
// Check if this is a content:// URI or a regular file path
2433+
if file_path.starts_with("content://") {
2434+
// Content URI - use Android ContentResolver
2435+
filesystem::read_android_uri(file_path)?
2436+
} else {
2437+
// Regular file path (e.g., marketplace apps) - use standard file I/O
2438+
let path = std::path::Path::new(&file_path);
2439+
2440+
if !path.exists() {
2441+
return Err(format!("File does not exist: {}", file_path));
2442+
}
2443+
2444+
let bytes = std::fs::read(&file_path)
2445+
.map_err(|e| format!("Failed to read file: {}", e))?;
2446+
2447+
if bytes.is_empty() {
2448+
return Err(format!("File is empty (0 bytes): {}", file_path));
2449+
}
2450+
2451+
let extension = file_path
2452+
.rsplit('.')
2453+
.next()
2454+
.unwrap_or("bin")
2455+
.to_lowercase();
2456+
2457+
AttachmentFile {
2458+
bytes,
2459+
img_meta: None,
2460+
extension,
2461+
}
2462+
}
24052463
}
24062464
}
24072465
};

0 commit comments

Comments
 (0)