improve handling of file intents
This commit is contained in:
@@ -20,6 +20,8 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:mime/mime.dart' as mime;
|
||||
import 'package:nullability/nullability.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:riverpod/riverpod.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:simple_intent_receiver/simple_intent_receiver.dart';
|
||||
@@ -44,13 +46,37 @@ final _sharingIntentTransformer =
|
||||
|
||||
if (data != null) {
|
||||
if (uri_to_file.isUriSupported(data)) {
|
||||
final file = await uri_to_file.toFile(data);
|
||||
final mimeType = mime.lookupMimeType(file.path);
|
||||
switch (mimeType) {
|
||||
case 'application/pdf':
|
||||
sink.add(ReceivedIntentParameter(data, null));
|
||||
default:
|
||||
logger.w('Unhandled mime type: $mimeType');
|
||||
var path = data;
|
||||
if (p.extension(data).whenNotEmpty == null) {
|
||||
if (intent.mimeType.whenNotEmpty != null) {
|
||||
final ext = mime.extensionFromMime(intent.mimeType!);
|
||||
if (ext != null) {
|
||||
path = p.setExtension(path, '.$ext');
|
||||
} else {
|
||||
logger.w(
|
||||
'Could not determine file extension for: ${intent.mimeType}',
|
||||
);
|
||||
}
|
||||
} else {
|
||||
logger.w(
|
||||
'Received intent without extension and mime type $path',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
final file = await uri_to_file.toFile(path);
|
||||
final mimeType = mime.lookupMimeType(file.path);
|
||||
switch (mimeType) {
|
||||
case 'application/pdf':
|
||||
sink.add(ReceivedIntentParameter(path, null));
|
||||
default:
|
||||
logger.w('Unhandled mime type: $mimeType');
|
||||
}
|
||||
} catch (e) {
|
||||
logger.e('Failed to convert URI to file: $e');
|
||||
// Fallback: pass the original URI
|
||||
sink.add(ReceivedIntentParameter(data, null));
|
||||
}
|
||||
} else {
|
||||
sink.add(ReceivedIntentParameter(data, null));
|
||||
|
||||
+34
-13
@@ -3,6 +3,7 @@ package eu.weblibre.simple_intent_receiver
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import io.flutter.Log
|
||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||
@@ -30,10 +31,8 @@ class SimpleIntentReceiverPlugin: FlutterPlugin, ActivityAware, PluginRegistry.N
|
||||
activity = binding.activity
|
||||
binding.addOnNewIntentListener(this)
|
||||
|
||||
// Process the initial intent if available
|
||||
binding.activity.intent?.let { intent ->
|
||||
val uri = intent.toUri(0);
|
||||
|
||||
val uri = intent.toUri(0)
|
||||
if (lastHandledIntent != uri) {
|
||||
handleIntent(intent)
|
||||
lastHandledIntent = uri
|
||||
@@ -55,15 +54,43 @@ class SimpleIntentReceiverPlugin: FlutterPlugin, ActivityAware, PluginRegistry.N
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent): Boolean {
|
||||
// Update the activity's intent to ensure proper state
|
||||
activity?.setIntent(intent)
|
||||
return handleIntent(intent)
|
||||
}
|
||||
|
||||
private fun handleIntent(intent: Intent): Boolean {
|
||||
// Check if this intent is coming from a different task
|
||||
// Grant URI permissions for content URIs
|
||||
intent.data?.let { uri ->
|
||||
if (uri.scheme == "content") {
|
||||
try {
|
||||
activity?.grantUriPermission(
|
||||
context.packageName,
|
||||
uri,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Log.w("SimpleIntentReceiver", "Could not grant URI permission for: $uri", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle SEND action with STREAM extra
|
||||
intent.getStringExtra(Intent.EXTRA_STREAM)?.let { streamUri ->
|
||||
try {
|
||||
val uri = Uri.parse(streamUri)
|
||||
if (uri.scheme == "content") {
|
||||
activity?.grantUriPermission(
|
||||
context.packageName,
|
||||
uri,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.w("SimpleIntentReceiver", "Could not grant URI permission for stream: $streamUri", e)
|
||||
}
|
||||
}
|
||||
|
||||
if (intent.flags and Intent.FLAG_ACTIVITY_NEW_TASK != 0) {
|
||||
// Clear any existing tasks with this activity
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
}
|
||||
|
||||
@@ -77,25 +104,20 @@ class SimpleIntentReceiverPlugin: FlutterPlugin, ActivityAware, PluginRegistry.N
|
||||
val data = intent.dataString
|
||||
val fromPackageName = intent.getPackage()
|
||||
|
||||
// Extract categories
|
||||
val categories = ArrayList<String>()
|
||||
intent.categories?.let {
|
||||
categories.addAll(it)
|
||||
}
|
||||
|
||||
// Extract extras
|
||||
val extras = HashMap<String, Any?>()
|
||||
intent.extras?.let { bundle ->
|
||||
for (key in bundle.keySet()) {
|
||||
try {
|
||||
when (val value = bundle.get(key)) {
|
||||
// Handle Bundle objects specially
|
||||
is Bundle -> {
|
||||
// Convert nested Bundle to Map
|
||||
val bundleMap = HashMap<String, Any?>()
|
||||
for (bundleKey in value.keySet()) {
|
||||
val bundleValue = value.get(bundleKey)
|
||||
// Only add primitive types and strings that can be safely serialized
|
||||
if (bundleValue == null || bundleValue is String ||
|
||||
bundleValue is Boolean || bundleValue is Int ||
|
||||
bundleValue is Long || bundleValue is Double ||
|
||||
@@ -107,12 +129,10 @@ class SimpleIntentReceiverPlugin: FlutterPlugin, ActivityAware, PluginRegistry.N
|
||||
}
|
||||
extras[key] = bundleMap
|
||||
}
|
||||
// Handle other types that Flutter can serialize
|
||||
null, is String, is Boolean, is Int, is Long, is Double, is Float,
|
||||
is ByteArray, is IntArray, is LongArray, is DoubleArray, is FloatArray -> {
|
||||
extras[key] = value
|
||||
}
|
||||
// For any other types, convert to string
|
||||
else -> {
|
||||
extras[key] = value.toString()
|
||||
}
|
||||
@@ -129,6 +149,7 @@ class SimpleIntentReceiverPlugin: FlutterPlugin, ActivityAware, PluginRegistry.N
|
||||
action = action,
|
||||
data = data,
|
||||
categories = categories,
|
||||
mimeType = intent.type,
|
||||
extra = extras
|
||||
)
|
||||
}
|
||||
|
||||
+6
-3
@@ -1,4 +1,4 @@
|
||||
// Autogenerated from Pigeon (v25.5.0), do not edit directly.
|
||||
// Autogenerated from Pigeon (v26.0.0), do not edit directly.
|
||||
// See also: https://pub.dev/packages/pigeon
|
||||
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
|
||||
|
||||
@@ -67,6 +67,7 @@ data class Intent (
|
||||
val action: String? = null,
|
||||
val data: String? = null,
|
||||
val categories: List<String>,
|
||||
val mimeType: String? = null,
|
||||
val extra: Map<String, Any?>
|
||||
)
|
||||
{
|
||||
@@ -76,8 +77,9 @@ data class Intent (
|
||||
val action = pigeonVar_list[1] as String?
|
||||
val data = pigeonVar_list[2] as String?
|
||||
val categories = pigeonVar_list[3] as List<String>
|
||||
val extra = pigeonVar_list[4] as Map<String, Any?>
|
||||
return Intent(fromPackageName, action, data, categories, extra)
|
||||
val mimeType = pigeonVar_list[4] as String?
|
||||
val extra = pigeonVar_list[5] as Map<String, Any?>
|
||||
return Intent(fromPackageName, action, data, categories, mimeType, extra)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
@@ -86,6 +88,7 @@ data class Intent (
|
||||
action,
|
||||
data,
|
||||
categories,
|
||||
mimeType,
|
||||
extra,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Autogenerated from Pigeon (v25.5.0), do not edit directly.
|
||||
// Autogenerated from Pigeon (v26.0.0), do not edit directly.
|
||||
// See also: https://pub.dev/packages/pigeon
|
||||
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers
|
||||
|
||||
@@ -38,6 +38,7 @@ class Intent {
|
||||
this.action,
|
||||
this.data,
|
||||
required this.categories,
|
||||
this.mimeType,
|
||||
required this.extra,
|
||||
});
|
||||
|
||||
@@ -49,6 +50,8 @@ class Intent {
|
||||
|
||||
List<String> categories;
|
||||
|
||||
String? mimeType;
|
||||
|
||||
Map<String, Object?> extra;
|
||||
|
||||
List<Object?> _toList() {
|
||||
@@ -57,6 +60,7 @@ class Intent {
|
||||
action,
|
||||
data,
|
||||
categories,
|
||||
mimeType,
|
||||
extra,
|
||||
];
|
||||
}
|
||||
@@ -71,7 +75,8 @@ class Intent {
|
||||
action: result[1] as String?,
|
||||
data: result[2] as String?,
|
||||
categories: (result[3] as List<Object?>?)!.cast<String>(),
|
||||
extra: (result[4] as Map<Object?, Object?>?)!.cast<String, Object?>(),
|
||||
mimeType: result[4] as String?,
|
||||
extra: (result[5] as Map<Object?, Object?>?)!.cast<String, Object?>(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ class Intent {
|
||||
final String? action;
|
||||
final String? data;
|
||||
final List<String> categories;
|
||||
final String? mimeType;
|
||||
final Map<String, Object?> extra;
|
||||
|
||||
Intent({
|
||||
@@ -12,6 +13,7 @@ class Intent {
|
||||
required this.action,
|
||||
required this.data,
|
||||
required this.categories,
|
||||
required this.mimeType,
|
||||
required this.extra,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user