Android Xamarin:基于存储路径打开各类文件的实现需求
Hey there! Let's figure out how to make your app prompt users to choose an external app for .docx, .xlsx, and other non-PDF files, while keeping your existing WebView PDF handling intact. Here's a step-by-step solution tailored to common mobile development frameworks (I'll cover Android and iOS examples since those are the most common targets):
Start by extending your existing file type check. We'll keep the PDF WebView flow and add a new branch for other file types to trigger the system's app chooser:
var fileType = path.Split('.').Last().ToLower(); if (fileType == "pdf") { // Keep your existing WebView PDF opening logic here LoadPdfInWebView(path); } else { // Trigger system app chooser for .docx, .xlsx, etc. OpenFileWithSystemChooser(path); }
Android Implementation
On Android, we'll use an Intent.ACTION_VIEW to let the system handle file opening, and use FileProvider (required for Android 7.0+) to avoid security exceptions when sharing file URIs.
1. Add the App Chooser Method
private void OpenFileWithSystemChooser(string filePath) { var targetFile = new Java.IO.File(filePath); // Get a secure content URI using FileProvider var fileUri = Android.Support.V4.Content.FileProvider.GetUriForFile( this, $"{PackageName}.fileprovider", // Match your provider authority in AndroidManifest targetFile); // Create the intent to view the file var openIntent = new Intent(Intent.ActionView); openIntent.SetDataAndType(fileUri, GetFileMimeType(filePath)); openIntent.AddFlags(ActivityFlags.GrantReadUriPermission); // Grant access to the app that opens the file openIntent.AddFlags(ActivityFlags.NewTask); // Show the app chooser dialog var chooser = Intent.CreateChooser(openIntent, "Select an app to open this file"); StartActivity(chooser); } // Helper to get the correct MIME type for the file private string GetFileMimeType(string filePath) { var defaultMime = "application/octet-stream"; var fileExtension = Path.GetExtension(filePath).TrimStart('.').ToLower(); var mimeMap = MimeTypeMap.Singleton; var mappedMime = mimeMap.GetMimeTypeFromExtension(fileExtension); return string.IsNullOrEmpty(mappedMime) ? defaultMime : mappedMime; }
2. Configure FileProvider in AndroidManifest.xml
Add this provider entry inside the <application> tag to enable secure URI sharing:
<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
3. Create the File Paths Configuration
Create a res/xml/file_paths.xml file to define which directories your app can share files from (adjust the path to match where you store downloaded files):
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Use external-files-path for files stored in your app's external files directory --> <external-files-path name="downloaded_files" path="." /> <!-- Use files-path for app-internal storage, or external-cache-path for cache files --> </paths>
iOS Implementation
On iOS, we'll use UIDocumentInteractionController to present the system's app chooser and preview options.
Add the App Chooser Method
private void OpenFileWithSystemChooser(string filePath) { var fileUrl = NSUrl.FromFilename(filePath); var docController = UIDocumentInteractionController.FromUrl(fileUrl); // Set a delegate to handle preview interactions docController.Delegate = new DocumentInteractionDelegate(this); // Present the app chooser menu docController.PresentOptionsMenu(View.Frame, View, true); } // Delegate class to support preview functionality public class DocumentInteractionDelegate : UIDocumentInteractionControllerDelegate { private readonly UIViewController _hostViewController; public DocumentInteractionDelegate(UIViewController host) { _hostViewController = host; } public override UIViewController ViewControllerForPreview(UIDocumentInteractionController controller) { return _hostViewController; } public override UIView ViewForPreview(UIDocumentInteractionController controller) { return _hostViewController.View; } }
- Permissions: Ensure your app has the necessary storage permissions:
- Android: Request
READ_EXTERNAL_STORAGE(for Android 10 and below) or use scoped storage practices for Android 11+. - iOS: Add usage descriptions in
Info.plist(e.g.,NSDocumentsFolderUsageDescription) if accessing user-facing storage.
- Android: Request
- MIME Types: The
GetFileMimeTypehelper ensures the system knows what kind of file it's handling, which helps find the right apps to open it. - Scoped Storage (Android 11+): If you're targeting Android 11 or higher, avoid direct file paths where possible—use MediaStore or Storage Access Framework (SAF) for better compatibility.
内容的提问来源于stack exchange,提问作者Aiko West

