diff --git a/plugins/fs/android/src/main/java/FsPlugin.kt b/plugins/fs/android/src/main/java/FsPlugin.kt index 877fbf4a..603cc950 100644 --- a/plugins/fs/android/src/main/java/FsPlugin.kt +++ b/plugins/fs/android/src/main/java/FsPlugin.kt @@ -7,8 +7,10 @@ package com.plugin.fs import android.annotation.SuppressLint import android.app.Activity import android.content.res.AssetManager.ACCESS_BUFFER +import android.database.Cursor import android.net.Uri import android.os.ParcelFileDescriptor +import android.provider.OpenableColumns import app.tauri.annotation.Command import app.tauri.annotation.InvokeArg import app.tauri.annotation.TauriPlugin @@ -33,6 +35,11 @@ class GetFileDescriptorArgs { lateinit var mode: String } +@InvokeArg +class GetFileNameArgs { + lateinit var uri: String +} + @TauriPlugin class FsPlugin(private val activity: Activity): Plugin(activity) { @SuppressLint("Recycle") @@ -89,5 +96,36 @@ class FsPlugin(private val activity: Activity): Plugin(activity) { } } } + + @Command + fun getFileName(invoke: Invoke) { + val args = invoke.parseArgs(GetFileNameArgs::class.java) + val res = JSObject() + val name = getRealNameFromURI(Uri.parse(args.uri)) + res.put("name", name) + invoke.resolve(res) + } + + fun getRealNameFromURI(contentUri: Uri): String? { + var cursor: Cursor? = null + try { + val projection = arrayOf(OpenableColumns.DISPLAY_NAME) + cursor = activity.contentResolver.query(contentUri, projection, null, null, null) + + cursor?.let { + val columnIndex = it.getColumnIndex(OpenableColumns.DISPLAY_NAME) + if (it.moveToFirst()) { + val FileName = it.getString(columnIndex) + return FileName + } + } + } catch (e: Exception) { + e.printStackTrace() + } finally { + cursor?.close() + } + + return null // Return null if no file name could be resolved + } } diff --git a/plugins/fs/src/mobile.rs b/plugins/fs/src/mobile.rs index 06422be6..a897a71c 100644 --- a/plugins/fs/src/mobile.rs +++ b/plugins/fs/src/mobile.rs @@ -8,7 +8,7 @@ use tauri::{ AppHandle, Runtime, }; -use crate::{models::*, FilePath, OpenOptions}; +use crate::{models::*, FilePath, OpenOptions, SafeFilePath}; #[cfg(target_os = "android")] const PLUGIN_IDENTIFIER: &str = "com.plugin.fs"; @@ -93,4 +93,25 @@ impl Fs { } } } + + pub fn file_name(&self, filepath: SafeFilePath) -> Result { + let uri; + match filepath { + SafeFilePath::Path(_) => unreachable!(), // Modern android uses content URIs so getting a path is not possible + SafeFilePath::Url(url) => { + uri = url.to_string(); + } + } + let Ok(result) = self.0.run_mobile_plugin::( + "getFileName", + GetFileNamePayload { uri }, + ) else { + return Err("Failed to invoke getFileName kotlin function".into()); + }; + if let Some(name) = result.name { + Ok(name) + } else { + Err("Failed to get file name".into()) + } + } } diff --git a/plugins/fs/src/models.rs b/plugins/fs/src/models.rs index b9edc2cb..33b265d6 100644 --- a/plugins/fs/src/models.rs +++ b/plugins/fs/src/models.rs @@ -11,8 +11,20 @@ pub struct GetFileDescriptorPayload { pub mode: String, } +#[derive(Debug, Clone, Default, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct GetFileNamePayload { + pub uri: String, +} + #[derive(Debug, Clone, Default, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct GetFileDescriptorResponse { pub fd: Option, } + +#[derive(Debug, Clone, Default, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct GetFileNameResponse { + pub name: Option, +} \ No newline at end of file