Xamarin Forms Android:文件分享与打开问题求助
Hey there, let's tackle your Xamarin.Android issues one by one!
文件分享问题:"Error loading. The request contains no data"
The root cause here is that Intent.ExtraStream expects a Uri, not a direct byte array. Android's share Intent can't process in-memory byte arrays directly—you need to first write the bytes to a temporary file, then use a FileProvider to get a valid Uri (critical for Android 7.0+ to avoid FileUriExposedException).
Step-by-step fix:
- Save your byte array to a temporary cache file
- Configure
FileProvider(if you haven't already) - Pass the Uri to your share Intent with proper permissions
Code to save byte array to temp file:
private string SaveByteArrayToTempFile(byte[] fileArray, string fileName) { var tempDir = Context.CacheDir; var tempFile = new File(tempDir, fileName); using (var stream = new FileStream(tempFile.AbsolutePath, FileMode.Create)) { stream.Write(fileArray, 0, fileArray.Length); } return tempFile.AbsolutePath; }
Updated share code:
byte[] fileArray = ....; string tempFilePath = SaveByteArrayToTempFile(fileArray, "MyFile.dat"); var sharingIntent = new Intent(Intent.ActionSend); sharingIntent.SetType("application/octet-stream"); // Get Uri via FileProvider (replace "com.yourpackage.name.fileprovider" with your app's authority) var fileUri = FileProvider.GetUriForFile(this, "com.yourpackage.name.fileprovider", new File(tempFilePath)); // Grant temporary read permission to the receiving app sharingIntent.AddFlags(ActivityFlags.GrantReadUriPermission); sharingIntent.PutExtra(Intent.ExtraStream, fileUri); StartActivity(Intent.CreateChooser(sharingIntent, "Send file"));
FileProvider configuration (add to AndroidManifest.xml):
<provider android:name="androidx.core.content.FileProvider" android:authorities="com.yourpackage.name.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
Create Resources/xml/file_paths.xml:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <cache-path name="temp_files" path="." /> </paths>
文件打开与转byte[]问题
The path you're getting from intent.Data.Path isn't a real filesystem path—it's a Content Uri (Android's file picker returns these for security starting from Android 6.0). Directly using the Path property will give you an invalid string. Instead, use ContentResolver to open an input stream from the Uri.
Code to handle both byte[] conversion and file opening:
protected override void OnActivityResult(int requestCode, Result resultCode, Intent intent) { base.OnActivityResult(requestCode, resultCode, intent); if (resultCode == Result.Ok && intent?.Data != null) { // Option 1: Convert file to byte[] byte[] fileBytes = ReadFileBytesFromUri(intent.Data); // Option 2: Open the file with the default app OpenFileWithDefaultApp(intent.Data); } } // Helper to read byte[] from Content Uri private byte[] ReadFileBytesFromUri(Uri uri) { using (var inputStream = ContentResolver.OpenInputStream(uri)) { if (inputStream == null) return null; using (var memoryStream = new MemoryStream()) { inputStream.CopyTo(memoryStream); return memoryStream.ToArray(); } } } // Helper to open file with default application private void OpenFileWithDefaultApp(Uri uri) { var openIntent = new Intent(Intent.ActionView); // Get the correct MIME type for the file string mimeType = ContentResolver.GetType(uri); openIntent.SetDataAndType(uri, mimeType); // Grant temporary read permission openIntent.AddFlags(ActivityFlags.GrantReadUriPermission); try { StartActivity(openIntent); } catch (ActivityNotFoundException) { Toast.MakeText(this, "No app found to open this file", ToastLength.Short).Show(); } }
This works for both your download folder Uri (/document/raw:/storage/emulated/0/Download/MyFile.dat) and SD card Uri (/document/1513-1812:MyFile.dat)—the ContentResolver handles resolving these Uri types automatically.
内容的提问来源于stack exchange,提问作者Neff

