mirror of
https://github.com/localsend/localsend.git
synced 2026-08-07 07:14:52 +00:00
feat(android): expose content URI file descriptor
This commit is contained in:
@@ -2,6 +2,7 @@ package org.localsend.localsend_app
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
import android.content.ContentResolver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
@@ -58,6 +59,8 @@ class MainActivity : FlutterActivity() {
|
|||||||
|
|
||||||
"createDirectory" -> handleCreateDirectory(call, result)
|
"createDirectory" -> handleCreateDirectory(call, result)
|
||||||
|
|
||||||
|
"getFileDescriptor" -> handleGetFileDescriptor(call, result)
|
||||||
|
|
||||||
"openContentUri" -> {
|
"openContentUri" -> {
|
||||||
openUri(context, call.argument<String>("uri")!!)
|
openUri(context, call.argument<String>("uri")!!)
|
||||||
result.success(null)
|
result.success(null)
|
||||||
@@ -82,6 +85,38 @@ class MainActivity : FlutterActivity() {
|
|||||||
Settings.Global.ANIMATOR_DURATION_SCALE, 1.0f) != 0.0f;
|
Settings.Global.ANIMATOR_DURATION_SCALE, 1.0f) != 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun handleGetFileDescriptor(call: MethodCall, result: MethodChannel.Result) {
|
||||||
|
val uriString = call.argument<String>("uri")
|
||||||
|
if (uriString == null) {
|
||||||
|
result.error("INVALID_ARGUMENT", "Missing content URI", null)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val uri = Uri.parse(uriString)
|
||||||
|
if (uri.scheme != ContentResolver.SCHEME_CONTENT) {
|
||||||
|
result.error("INVALID_ARGUMENT", "Expected a content:// URI", null)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
val parcelFileDescriptor = contentResolver.openFileDescriptor(uri, "r")
|
||||||
|
if (parcelFileDescriptor == null) {
|
||||||
|
result.error("OPEN_FAILED", "The content provider did not return a file descriptor", null)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ownership of the detached descriptor is transferred to the caller. It must be
|
||||||
|
// closed by Rust (or whichever native consumer receives it) after use.
|
||||||
|
parcelFileDescriptor.use {
|
||||||
|
result.success(it.detachFd())
|
||||||
|
}
|
||||||
|
} catch (e: SecurityException) {
|
||||||
|
result.error("PERMISSION_DENIED", e.message ?: "Permission denied for content URI", null)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
result.error("OPEN_FAILED", e.message ?: "Failed to open content URI", null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun openDirectoryPicker(onlyPath: Boolean) {
|
private fun openDirectoryPicker(onlyPath: Boolean) {
|
||||||
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
||||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
|
||||||
|
|||||||
@@ -44,6 +44,20 @@ Future<bool> getSystemAnimationsStatusAndroid() async {
|
|||||||
return await _methodChannel.invokeMethod('isAnimationsEnabled') ?? true;
|
return await _methodChannel.invokeMethod('isAnimationsEnabled') ?? true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Opens [uri] for reading and returns an owned Linux file descriptor.
|
||||||
|
///
|
||||||
|
/// The descriptor stays open after this call and must be closed by the native
|
||||||
|
/// consumer it is passed to.
|
||||||
|
Future<int> getFileDescriptorAndroid({required String uri}) async {
|
||||||
|
final fileDescriptor = await _methodChannel.invokeMethod<int>('getFileDescriptor', {
|
||||||
|
'uri': uri,
|
||||||
|
});
|
||||||
|
if (fileDescriptor == null) {
|
||||||
|
throw StateError('Android returned no file descriptor for $uri');
|
||||||
|
}
|
||||||
|
return fileDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> createDirectory({
|
Future<void> createDirectory({
|
||||||
required String documentUri,
|
required String documentUri,
|
||||||
required String directoryName,
|
required String directoryName,
|
||||||
|
|||||||
Reference in New Issue
Block a user