├── .gitignore ├── CHANGELOG.md ├── ISSUE_TEMPLATE.md ├── LICENSE ├── PULL_REQUEST_TEMPLATE.md ├── README.md ├── samples ├── Plugin.FilePicker.Sample.Forms.sln ├── Plugin.FilePicker.Sample.Forms │ ├── Droid │ │ ├── Assets │ │ │ └── AboutAssets.txt │ │ ├── MainActivity.cs │ │ ├── Plugin.FilePicker.Sample.Forms.Droid.csproj │ │ ├── Properties │ │ │ ├── AndroidManifest.xml │ │ │ └── AssemblyInfo.cs │ │ └── Resources │ │ │ ├── AboutResources.txt │ │ │ ├── Resource.designer.cs │ │ │ ├── drawable-hdpi │ │ │ └── icon.png │ │ │ ├── drawable-xhdpi │ │ │ └── icon.png │ │ │ ├── drawable-xxhdpi │ │ │ └── icon.png │ │ │ ├── drawable │ │ │ └── icon.png │ │ │ ├── layout │ │ │ ├── Tabbar.axml │ │ │ └── Toolbar.axml │ │ │ └── values │ │ │ └── styles.xml │ ├── Forms │ │ ├── App.xaml │ │ ├── App.xaml.cs │ │ ├── MainPage.xaml │ │ ├── MainPage.xaml.cs │ │ └── Plugin.FilePicker.Sample.Forms.csproj │ ├── UWP │ │ ├── App.xaml │ │ ├── App.xaml.cs │ │ ├── Assets │ │ │ ├── LargeTile.scale-100.png │ │ │ ├── LargeTile.scale-200.png │ │ │ ├── LargeTile.scale-400.png │ │ │ ├── SmallTile.scale-100.png │ │ │ ├── SmallTile.scale-200.png │ │ │ ├── SmallTile.scale-400.png │ │ │ ├── SplashScreen.scale-100.png │ │ │ ├── SplashScreen.scale-200.png │ │ │ ├── SplashScreen.scale-400.png │ │ │ ├── Square150x150Logo.scale-100.png │ │ │ ├── Square150x150Logo.scale-200.png │ │ │ ├── Square150x150Logo.scale-400.png │ │ │ ├── Square44x44Logo.altform-unplated_targetsize-16.png │ │ │ ├── Square44x44Logo.altform-unplated_targetsize-256.png │ │ │ ├── Square44x44Logo.altform-unplated_targetsize-48.png │ │ │ ├── Square44x44Logo.scale-100.png │ │ │ ├── Square44x44Logo.scale-200.png │ │ │ ├── Square44x44Logo.scale-400.png │ │ │ ├── Square44x44Logo.targetsize-16.png │ │ │ ├── Square44x44Logo.targetsize-256.png │ │ │ ├── Square44x44Logo.targetsize-48.png │ │ │ ├── StoreLogo.backup.png │ │ │ ├── StoreLogo.scale-100.png │ │ │ ├── StoreLogo.scale-200.png │ │ │ ├── StoreLogo.scale-400.png │ │ │ ├── Wide310x150Logo.scale-100.png │ │ │ ├── Wide310x150Logo.scale-200.png │ │ │ └── Wide310x150Logo.scale-400.png │ │ ├── MainPage.xaml │ │ ├── MainPage.xaml.cs │ │ ├── Package.appxmanifest │ │ ├── Plugin.FilePicker.Sample.Forms.UWP.csproj │ │ └── Properties │ │ │ ├── AssemblyInfo.cs │ │ │ └── Default.rd.xml │ ├── WPF │ │ ├── App.config │ │ ├── App.xaml │ │ ├── App.xaml.cs │ │ ├── MainWindow.xaml │ │ ├── MainWindow.xaml.cs │ │ ├── Plugin.FilePicker.Sample.Forms.WPF.csproj │ │ └── Properties │ │ │ ├── AssemblyInfo.cs │ │ │ ├── Resources.resx │ │ │ └── Settings.settings │ └── iOS │ │ ├── AppDelegate.cs │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ │ ├── Entitlements.plist │ │ ├── Info.plist │ │ ├── LaunchScreen.storyboard │ │ ├── Main.cs │ │ └── Plugin.FilePicker.Sample.Forms.iOS.csproj ├── Plugin.FilePicker.Sample.MacOS.sln ├── Plugin.FilePicker.Sample.MacOS │ ├── AppDelegate.cs │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── AppIcon-128.png │ │ │ ├── AppIcon-128@2x.png │ │ │ ├── AppIcon-16.png │ │ │ ├── AppIcon-16@2x.png │ │ │ ├── AppIcon-256.png │ │ │ ├── AppIcon-256@2x.png │ │ │ ├── AppIcon-32.png │ │ │ ├── AppIcon-32@2x.png │ │ │ ├── AppIcon-512.png │ │ │ ├── AppIcon-512@2x.png │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Entitlements.plist │ ├── Info.plist │ ├── Main.cs │ ├── Main.storyboard │ ├── Plugin.FilePicker.Sample.MacOS.csproj │ ├── ViewController.cs │ └── ViewController.designer.cs ├── Plugin.FilePicker.Sample.Wpf │ ├── App.xaml │ ├── App.xaml.cs │ ├── Core3.0 │ │ ├── AssemblyInfo.cs │ │ ├── MainWindow.3.0.cs │ │ └── Plugin.FilePicker.Sample.Wpf.Core3.0.csproj │ ├── Core3.1 │ │ ├── AssemblyInfo.cs │ │ ├── MainWindow.3.1.cs │ │ └── Plugin.FilePicker.Sample.Wpf.Core3.1.csproj │ ├── Framework │ │ ├── MainWindow.4.5.cs │ │ ├── MainWindow.4.6.cs │ │ ├── MainWindow.4.7.cs │ │ ├── MainWindow.4.8.cs │ │ ├── Plugin.FilePicker.Sample.Wpf.Framework4.5.csproj │ │ ├── Plugin.FilePicker.Sample.Wpf.Framework4.6.csproj │ │ ├── Plugin.FilePicker.Sample.Wpf.Framework4.7.csproj │ │ ├── Plugin.FilePicker.Sample.Wpf.Framework4.8.csproj │ │ └── Properties │ │ │ └── AssemblyInfo.cs │ ├── MainWindow.xaml │ └── MainWindow.xaml.cs └── README.md └── src ├── .droidres └── .plugin.filepicker.droidres.db ├── Plugin.FilePicker.sln └── Plugin.FilePicker ├── Android ├── FilePickerActivity.android.cs ├── FilePickerImplementation.android.cs └── IOUtil.android.cs ├── CrossFilePicker.shared.cs ├── FileData.shared.cs ├── FilePickerCancelledEventArgs.shared.cs ├── FilePickerEventArgs.shared.cs ├── FilePickerImplementation.ios.cs ├── FilePickerImplementation.mac.cs ├── FilePickerImplementation.net45.cs ├── FilePickerImplementation.uwp.cs ├── IFilePicker.shared.cs └── Plugin.FilePicker.csproj /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | 24 | # Visual Studio 2015 cache/options directory 25 | .vs/ 26 | # Uncomment if you have tasks that create the project's static files in wwwroot 27 | #wwwroot/ 28 | 29 | # MSTest test Results 30 | [Tt]est[Rr]esult*/ 31 | [Bb]uild[Ll]og.* 32 | 33 | # NUNIT 34 | *.VisualState.xml 35 | TestResult.xml 36 | 37 | # Build Results of an ATL Project 38 | [Dd]ebugPS/ 39 | [Rr]eleasePS/ 40 | dlldata.c 41 | 42 | # DNX 43 | project.lock.json 44 | artifacts/ 45 | 46 | *_i.c 47 | *_p.c 48 | *_i.h 49 | *.ilk 50 | *.meta 51 | *.obj 52 | *.pch 53 | *.pdb 54 | *.pgc 55 | *.pgd 56 | *.rsp 57 | *.sbr 58 | *.tlb 59 | *.tli 60 | *.tlh 61 | *.tmp 62 | *.tmp_proj 63 | *.log 64 | *.vspscc 65 | *.vssscc 66 | .builds 67 | *.pidb 68 | *.svclog 69 | *.scc 70 | 71 | # Chutzpah Test files 72 | _Chutzpah* 73 | 74 | # Visual C++ cache files 75 | ipch/ 76 | *.aps 77 | *.ncb 78 | *.opendb 79 | *.opensdf 80 | *.sdf 81 | *.cachefile 82 | 83 | # Visual Studio profiler 84 | *.psess 85 | *.vsp 86 | *.vspx 87 | *.sap 88 | 89 | # TFS 2012 Local Workspace 90 | $tf/ 91 | 92 | # Guidance Automation Toolkit 93 | *.gpState 94 | 95 | # ReSharper is a .NET coding add-in 96 | _ReSharper*/ 97 | *.[Rr]e[Ss]harper 98 | *.DotSettings.user 99 | 100 | # JustCode is a .NET coding add-in 101 | .JustCode 102 | 103 | # TeamCity is a build add-in 104 | _TeamCity* 105 | 106 | # DotCover is a Code Coverage Tool 107 | *.dotCover 108 | 109 | # NCrunch 110 | _NCrunch_* 111 | .*crunch*.local.xml 112 | nCrunchTemp_* 113 | 114 | # MightyMoose 115 | *.mm.* 116 | AutoTest.Net/ 117 | 118 | # Web workbench (sass) 119 | .sass-cache/ 120 | 121 | # Installshield output folder 122 | [Ee]xpress/ 123 | 124 | # DocProject is a documentation generator add-in 125 | DocProject/buildhelp/ 126 | DocProject/Help/*.HxT 127 | DocProject/Help/*.HxC 128 | DocProject/Help/*.hhc 129 | DocProject/Help/*.hhk 130 | DocProject/Help/*.hhp 131 | DocProject/Help/Html2 132 | DocProject/Help/html 133 | 134 | # Click-Once directory 135 | publish/ 136 | 137 | # Publish Web Output 138 | *.[Pp]ublish.xml 139 | *.azurePubxml 140 | # TODO: Comment the next line if you want to checkin your web deploy settings 141 | # but database connection strings (with potential passwords) will be unencrypted 142 | *.pubxml 143 | *.publishproj 144 | 145 | # NuGet Packages 146 | *.nupkg 147 | # The packages folder can be ignored because of Package Restore 148 | **/packages/* 149 | # except build/, which is used as an MSBuild target. 150 | !**/packages/build/ 151 | # Uncomment if necessary however generally it will be regenerated when needed 152 | #!**/packages/repositories.config 153 | # NuGet v3's project.json files produces more ignoreable files 154 | *.nuget.props 155 | *.nuget.targets 156 | 157 | # Microsoft Azure Build Output 158 | csx/ 159 | *.build.csdef 160 | 161 | # Microsoft Azure Emulator 162 | ecf/ 163 | rcf/ 164 | 165 | # Microsoft Azure ApplicationInsights config file 166 | ApplicationInsights.config 167 | 168 | # Windows Store app package directory 169 | AppPackages/ 170 | BundleArtifacts/ 171 | 172 | # Visual Studio cache files 173 | # files ending in .cache can be ignored 174 | *.[Cc]ache 175 | # but keep track of directories ending in .cache 176 | !*.[Cc]ache/ 177 | 178 | # Others 179 | ClientBin/ 180 | ~$* 181 | *~ 182 | *.dbmdl 183 | *.dbproj.schemaview 184 | *.pfx 185 | *.publishsettings 186 | node_modules/ 187 | orleans.codegen.cs 188 | 189 | # RIA/Silverlight projects 190 | Generated_Code/ 191 | 192 | # Backup & report files from converting an old project file 193 | # to a newer Visual Studio version. Backup files are not needed, 194 | # because we have git ;-) 195 | _UpgradeReport_Files/ 196 | Backup*/ 197 | UpgradeLog*.XML 198 | UpgradeLog*.htm 199 | 200 | # SQL Server files 201 | *.mdf 202 | *.ldf 203 | 204 | # Business Intelligence projects 205 | *.rdl.data 206 | *.bim.layout 207 | *.bim_*.settings 208 | 209 | # Microsoft Fakes 210 | FakesAssemblies/ 211 | 212 | # GhostDoc plugin setting file 213 | *.GhostDoc.xml 214 | 215 | # Node.js Tools for Visual Studio 216 | .ntvs_analysis.dat 217 | 218 | # Visual Studio 6 build log 219 | *.plg 220 | 221 | # Visual Studio 6 workspace options file 222 | *.opt 223 | 224 | # Visual Studio LightSwitch build output 225 | **/*.HTMLClient/GeneratedArtifacts 226 | **/*.DesktopClient/GeneratedArtifacts 227 | **/*.DesktopClient/ModelManifest.xml 228 | **/*.Server/GeneratedArtifacts 229 | **/*.Server/ModelManifest.xml 230 | _Pvt_Extensions 231 | 232 | # Paket dependency manager 233 | .paket/paket.exe 234 | 235 | # FAKE - F# Make 236 | .fake/ 237 | 238 | FilePicker/.DS_Store 239 | 240 | .DS_Store 241 | 242 | *.userprefs 243 | 244 | src/.droidres/.filepicker.droidres.db 245 | 246 | samples/Plugin.FilePicker.Sample.Forms/.droidres/.plugin.filepicker.sample.forms.droidres.db 247 | 248 | samples/Plugin.FilePicker.Sample.Forms/.droidres/.plugin.filepicker.sample.macos.droidres.db 249 | 250 | samples/.droidres/.plugin.filepicker.sample.forms.droidres.db 251 | 252 | src/.mfractor/.plugin.filepicker.db 253 | 254 | Resource.designer.cs 255 | Resources.Designer.cs 256 | Settings.Designer.cs 257 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Version 2.1.xx 4 | 5 | Android: When a `content://` URI is returned for a picked file, the plugin now 6 | tries to keep permissions to the picked content (#172, #158). 7 | 8 | ## Version 2.1.34 9 | 10 | (Re-)added SourceLink support 11 | 12 | ## Version 2.1.18 13 | 14 | Release version. No code changes since the version 2.1.17-beta. 15 | 16 | ## Version 2.1.17-beta 17 | 18 | Android: Fixed NullReferenceException caused by the bugfix from version 2.1.16-beta. 19 | 20 | ## Version 2.1.16-beta 21 | 22 | Android: Fixed error "Only one operation can be active at a time" when re-entering PickFile() 23 | call; now the first call returns null (#131). 24 | 25 | ## Version 2.1.12-beta 26 | 27 | Android: Fixed warning when compiling for TargetFrameworkVersion below 9.0 and using file picker 28 | from NuGet package (#125). 29 | 30 | WPF: Fixed using NuGet package under WPF by actually compiling the FilePicker plugin for .NET 4.5 31 | and higher (#122) (#124). 32 | 33 | Marked IFilePicker.OpenFile() and IFilePicker.SaveFile() obsolete; the plugin focuses on picking 34 | files. Will be removed in 2.2.x. 35 | 36 | ## Version 2.1.11-beta 37 | 38 | The plugin now uses multi-targeting; no visible changes to the API, but the NuGet package 39 | explicitly lists on which platforms the plugin can be installed. 40 | 41 | The plugin now uses SourceLink; when the Visual Studio option "Just my code" is deactivated, 42 | the user can directly debug into the plugin's code. See https://github.com/dotnet/sourcelink/ 43 | 44 | ## Version 2.0.135 45 | 46 | Android: When the app doesn't have Permission.ReadExternalStorage granted yet, the app will now 47 | ask the user to grant the permission (on API level >=23). The caller of PickFile() doesn't need to 48 | request permissions now. The permission is automatically added to the app when referencing this 49 | NuGet package. 50 | 51 | ## Version 2.0.121 52 | 53 | WPF: Implemented FilePicker for WPF (#64). 54 | 55 | Android: Fixed OpenFile() call with relative filename that uses wrong parent directory (#71). 56 | 57 | Android: Fixed stack overflow when calling OpenFile() with FileData argument. 58 | 59 | Marked FileData.ReadFully() obsolete; it shouldn't be used outside of the plugin. Will be removed 60 | in 2.1.x. 61 | 62 | ## Version 2.0.114-beta 63 | 64 | Android: Fixed getting path from OneDrive content provider (#79). 65 | 66 | Android/iOS: File bytes are not read directly after picking, but only when FileData.DataArray is 67 | accessed or FileData.GetStream() is called; this fixes accessing large files that wouldn't fit in 68 | the device's memory, e.g. videos (#38). 69 | 70 | ## Version 2.0.106-beta 71 | 72 | Android/iOS: PickFile() now throws more exceptions when an error while picking occured; before 73 | that some error states were silently discarded. 74 | 75 | Android: Added check if Android permission was granted; caller of PickFile() has to request 76 | permission, though. 77 | 78 | Android: Fixed exception when trying to pick a downloaded file; the Android DownloadManager won't 79 | return an actual file path; downloaded files can only be resolved using ContentResolver (#86). 80 | 81 | Android: fix android mime types implementation (#85) 82 | 83 | iOS: Fixed getting pathname from FileUrl (fix of PR #54 that was reverted in PR #65). 84 | 85 | ## Version 2.0.81-beta 86 | 87 | Added support for file types across platforms (#26). 88 | 89 | Revert pull request "Fixed Path" (#65). 90 | 91 | ## Version 2.0.64-beta 92 | 93 | Android: Fixed Path (#54); was returning File Url which cannot be used for file operations from 94 | PCL / Shared Project, instead returning path. 95 | 96 | ## Version 2.0.58-beta 97 | 98 | Fixed more NuGet package issues (#19, #23, #29). 99 | 100 | UWP: Make UWP streamGetter use StorageFile's OpenStreamForRead method, instead of trying to use 101 | the file path and File.IO (#33). 102 | 103 | Android: Support for content:// picked files (#22). 104 | 105 | Android: Fixed picking files from OneDrive; the ContentProvider returns no _data column (#44). 106 | 107 | Fixes crash in Xamarin.Forms sample when user doesn't select file; also added example code in README file (#50) 108 | 109 | Android: Fixed picking files from the download folder; on newer devices the document ID may not be 110 | a number, but the real filename prefixed with "raw:" (#49) 111 | 112 | ## Version 2.0.8-beta 113 | 114 | Fixed NuGet package issue (#13). 115 | 116 | ## Version 2.0.2-beta 117 | 118 | The plugin was converted from using PCL to using .NET Standard, with platform support for Android, 119 | iOS and UWP platforms. 120 | 121 | Removed Windows Phone 8 and Windows 8/8.1 support. 122 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Expected Behavior 2 | 3 | 4 | ## Actual Behavior 5 | 6 | 7 | ## Steps to Reproduce the Problem 8 | 9 | 1. 10 | 1. 11 | 1. 12 | 13 | ## Specifications 14 | 15 | - NuGet package version: 16 | - Platform(s): -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 jfversluis - Xamarin & .NET 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Description of Change ### 2 | 3 | 4 | 5 | ### Issues Resolved ### 6 | 7 | 8 | - fixes # 9 | 10 | ### Platforms Affected ### 11 | 12 | 13 | - iOS 14 | - Android 15 | - UWP 16 | - WPF 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FilePicker Plugin for Xamarin.Forms 2 | 3 | Simple cross-platform plug-in that allows you to pick files and work with them. 4 | 5 | The original project can be found [here](https://github.com/Studyxnet/FilePicker-Plugin-for-Xamarin-and-Windows/), but seems abandoned, this one was forked and further developed. 6 | 7 | ### The future: [Xamarin.Essentials](https://docs.microsoft.com/xamarin/essentials/) 8 | 9 | Since version 1.6.0 the [Xamarin.Essentials](https://github.com/xamarin/Essentials) 10 | project also supports file picking! See the [Migration Guide](#migration-guide) 11 | on how to migrate from this plugin to the official Xamarin.Essentials API! 12 | 13 | ## Build status 14 | ### Stable [![Build status](https://jfversluis.visualstudio.com/FilePicker%20plugin/_apis/build/status/FilePicker%20Plugin)](https://jfversluis.visualstudio.com/FilePicker%20plugin/_build/latest?definitionId=36) [![NuGet version](https://badge.fury.io/nu/Xamarin.Plugin.FilePicker.svg)](https://badge.fury.io/nu/Xamarin.Plugin.FilePicker) 15 | 16 | NuGet: [https://www.nuget.org/packages/Xamarin.Plugin.FilePicker/](https://www.nuget.org/packages/Xamarin.Plugin.FilePicker/) 17 | 18 | ### Development feed (possibly instable) 19 | 20 | Add this as a source to your IDE to find the latest packages: [https://www.myget.org/F/filepicker-plugin/api/v3/index.json](https://www.myget.org/F/filepicker-plugin/api/v3/index.json) 21 | 22 | ## Setup 23 | 24 | * Install into your Xamarin.Android, Xamarin.iOS, Xamarin.Forms, Xamarin.Mac, Xamarin.WPF project and Client projects. 25 | 26 | **Platform Support** 27 | 28 | | Platform |Supported| Version |Remarks| 29 | | ------------------------ | :-: | :------: | :------------------: | 30 | |Xamarin.iOS Classic | Yes | iOS 8+ || 31 | |Xamarin.iOS Unified | Yes | iOS 8+ || 32 | |Xamarin.Android | Yes | API 10+ || 33 | |Windows Phone Silverlight | No | || 34 | |Windows Phone RT | Yes | 8.1+ |Up to package version 1.4.x| 35 | |Windows Store RT | Yes | 8.1+ |Up to package version 1.4.x| 36 | |Windows 10 UWP | Yes | 10+ || 37 | |Xamarin.Mac | Yes | * 10.12+ || 38 | |WPF | Yes | N/A |Using .NET Framework 4.5| 39 | 40 | \* The Xamarin.Mac implementation has only been tested on MacOS 10.12. 41 | 42 | ### API Usage 43 | 44 | Call **CrossFilePicker.Current** from any platform or .NET Standard project to gain access to APIs. 45 | 46 | ### Example 47 | 48 | try 49 | { 50 | FileData fileData = await CrossFilePicker.Current.PickFile(); 51 | if (fileData == null) 52 | return; // user canceled file picking 53 | 54 | string fileName = fileData.FileName; 55 | string contents = System.Text.Encoding.UTF8.GetString(fileData.DataArray); 56 | 57 | System.Console.WriteLine("File name chosen: " + fileName); 58 | System.Console.WriteLine("File data: " + contents); 59 | } 60 | catch (Exception ex) 61 | { 62 | System.Console.WriteLine("Exception choosing file: " + ex.ToString()); 63 | } 64 | 65 | ### Methods 66 | 67 | #### `async Task PickFile(string[] allowedTypes = null)` 68 | 69 | Starts file picking and returns file data for picked file. File types can be 70 | specified in order to limit files that can be selected. Note that this method 71 | may throw exceptions that occured during file picking. 72 | 73 | Note that on Android it can happen that PickFile() can be called twice. In 74 | this case the first PickFile() call will return null as it is effectively 75 | cancelled. 76 | 77 | Parameter `allowedTypes`: 78 | Specifies one or multiple allowed types. When null, all file types can be 79 | selected while picking. 80 | 81 | On Android you can specify one or more MIME types, e.g. "image/png"; also wild 82 | card characters can be used, e.g. "image/*". 83 | 84 | On iOS you can specify UTType constants, e.g. UTType.Image. 85 | 86 | On UWP, specify a list of extensions, like this: `".jpg", ".png"`. 87 | 88 | On WPF, specify strings like this: `"Data type (*.ext)|*.ext"`, which 89 | corresponds how the Windows file open dialog specifies file types. 90 | 91 | ### Data structures 92 | 93 | The returned `FileData` object contains multiple properties that can be accessed: 94 | 95 | public class FileData 96 | { 97 | /// When accessed, reads all data from the picked file and returns it. 98 | public byte[] DataArray { get; } 99 | 100 | /// Filename of the picked file; doesn't contain any path. 101 | public string FileName { get; } 102 | 103 | /// Full file path of the picked file; note that on some platforms the 104 | /// file path may not be a real, accessible path but may contain an 105 | /// platform specific URI; may also be null. 106 | public string FilePath { get; } 107 | 108 | /// Returns a stream to the picked file; this is the most reliable way 109 | /// to access the data of the picked file. 110 | public Stream GetStream(); 111 | } 112 | 113 | Note that `DataArray` is filled on first access, so be sure to rewind the stream when 114 | you access it via GetStream() afterwards. 115 | 116 | ### **IMPORTANT** 117 | **Android:** 118 | The FilePath property may contain a content URI that starts with `content://`. 119 | The plugin tries hard to find out an actual filename, but when it can't, the 120 | file can only be accessed using `GetStream()` or `DataArray`. On Android 121 | `ContentProvider` classes are used to share data between apps. The resource 122 | that is accessed may not even be a file, streamed over the internet or loaded 123 | from a database. 124 | 125 | The plugin also tries to get a persistable content URI that can be stored for 126 | later access. Be prepared that this may fail, though. Content could have been 127 | moved to a different location or could be deleted. 128 | 129 | The `READ_EXTERNAL_STORAGE` permission is automatically added to your Android 130 | app project. Starting from Android 6.0 (Marshmallow) the user is asked for the 131 | permission when not granted yet. When the user denies the permission, 132 | `PickFile()` returns null. 133 | 134 | The `WRITE_EXTERNAL_STORAGE` is required if you call SaveFile() and must be 135 | added to your Android app project by yourself. 136 | 137 | **iOS:** 138 | You need to [Configure iCloud Driver for your app](https://developer.xamarin.com/guides/ios/platform_features/intro_to_cloudkit). 139 | 140 | ## Migration guide 141 | 142 | Migrating the usage of this FilePicker plugin to `Xamarin.Essentials.FilePicker` 143 | isn't straight-forward. It's similar, though, since the Essentials code 144 | originated from this plugin. Here's a little guide on how to do it. 145 | 146 | 1. If you don't have the Xamarin.Essentials NuGet package installed yet, install 147 | it into the Android, iOS and UWP projects. Also install it into your Forms 148 | project, if you're calling the FilePicker from there. Be sure to also 149 | properly [initialize Essentials](https://docs.microsoft.com/xamarin/essentials/get-started). 150 | You can remove the Xamarin.Plugin.FilePicker NuGet package now or afterwards. 151 | 152 | 2. Rename the namespaces, types and method calls. Replace 153 | 154 | using Plugin.FilePicker; 155 | using Plugin.FilePicker.Abstractions; 156 | 157 | with 158 | 159 | using Xamarin.Essentials; 160 | 161 | Replace `await CrossFilePicker.Current.PickFile()` with 162 | `await FilePicker.PickAsync()`. Replace `FileData` with `FileResult` (or 163 | use the `var` keyword). 164 | 165 | 3. Use `Xamarin.Essentials.PickOptions` if you specified file types for picking. 166 | Replace code like this: 167 | 168 | string[] fileTypes = null; 169 | if (Device.RuntimePlatform == Device.Android) 170 | fileTypes = new string[] { "image/png", "image/jpeg" }; 171 | 172 | if (Device.RuntimePlatform == Device.iOS) 173 | fileTypes = new string[] { "public.image" }; 174 | 175 | if (Device.RuntimePlatform == Device.UWP) 176 | fileTypes = new string[] { ".jpg", ".png" }; 177 | 178 | with: 179 | 180 | var options = new PickOptions 181 | { 182 | FileTypes = new FilePickerFileType( 183 | new Dictionary> 184 | { 185 | { DevicePlatform.Android, new string[] { "image/png", "image/jpeg"} }, 186 | { DevicePlatform.iOS, new string[] { "public.image" } }, 187 | { DevicePlatform.UWP, new string[] { ".jpg", ".png" } }, 188 | }), 189 | PickerTitle = "Select a file to import" 190 | }; 191 | 192 | If you can't specify a list of MIME types or file extensions, use `null` 193 | as the value of the dictionary entry, or else file picking on that platform 194 | won't be available: 195 | 196 | { DevicePlatform.Android, null }, 197 | 198 | Note also that the `PickerTitle` is a new property, but the title is only 199 | shown on Android. 200 | 201 | 4. Replace usage of `FileData` with `Xamarin.Essentials.FileResult`. The new 202 | FileResult structure has some properties and methods named differently. The 203 | biggest change is that you should not (and in some cases on Android can't) 204 | rely on `FileResult.FullPath` to be a file system filename. Always use 205 | `FileResult.OpenStreamAsync()` to get a stream to the picked file. From 206 | there you can either read from the stream directly (e.g. using a 207 | `StreamReader`), or copy the file into your app folder. This can be done 208 | using `Stream.CopyToAsync()` and has the advantage that you do the copying 209 | in a background task, and you can specify a `CancellationToken` that can 210 | be used to cancel the operation. You could even show a progress dialog to 211 | the user that allows cancelling the transfer. 212 | 213 | 214 | ## Troubleshooting 215 | 216 | ### All platforms 217 | 218 | **InvalidOperationException "Only one operation can be active at a time"** 219 | 220 | This occurs when `PickFile()` is called multiple times and the task being awaited didn't return or 221 | throws an exception that wasn't caught. Be sure to catch any exceptions and handle them 222 | appropriately. See the example code above. 223 | 224 | ### Android 225 | 226 | **Exception "This functionality is not implemented in the portable version of this assembly. You should reference the NuGet package from your main application project in order to reference the platform-specific implementation."** 227 | 228 | This occurs when you are using the old-style NuGet references (not the PackageReference mechanism) 229 | and you forgot to add the NuGet package to the Android package. When using PackageReference this 230 | is not necessary anymore because the bait-and-switch assemblies of FilePicker are correctly 231 | resolved. 232 | 233 | ### iOS 234 | 235 | **Picked file path is invalid, file doesn't exist** 236 | 237 | On iOS the plugin uses UIDocumentPickerViewController and specifies the mode 238 | UIDocumentPickerMode.Import. After picking is done, iOS copies the picked file 239 | to the app's temporary "Inbox" folder where it can be accessed. iOS also cleans up the 240 | temporary inbox folder regularly. After picking the file you have to either 241 | copy the file to another folder, access the data by getting the property 242 | DataArray or opening a stream to the file by calling GetStream(). 243 | 244 | ## Contributors 245 | * [jfversluis](https://github.com/jfversluis) 246 | * [rafaelrmou](https://github.com/rafaelrmou) (original author) 247 | * [vividos](https://github.com/vividos) 248 | 249 | Thanks! 250 | 251 | ## License 252 | [MIT Licence](LICENSE) 253 | -------------------------------------------------------------------------------- /samples/Plugin.FilePicker.Sample.Forms/Droid/Assets/AboutAssets.txt: -------------------------------------------------------------------------------- 1 | Any raw assets you want to be deployed with your application can be placed in 2 | this directory (and child directories) and given a Build Action of "AndroidAsset". 3 | 4 | These files will be deployed with your package and will be accessible using Android's 5 | AssetManager, like this: 6 | 7 | public class ReadAsset : Activity 8 | { 9 | protected override void OnCreate (Bundle bundle) 10 | { 11 | base.OnCreate (bundle); 12 | 13 | InputStream input = Assets.Open ("my_asset.txt"); 14 | } 15 | } 16 | 17 | Additionally, some Android functions will automatically load asset files: 18 | 19 | Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); 20 | -------------------------------------------------------------------------------- /samples/Plugin.FilePicker.Sample.Forms/Droid/MainActivity.cs: -------------------------------------------------------------------------------- 1 | using Android.App; 2 | using Android.Content.PM; 3 | using Android.OS; 4 | 5 | namespace Plugin.FilePicker.Sample.Forms.Droid 6 | { 7 | [Activity(Label = "Plugin.FilePicker.Sample.Forms.Droid", Icon = "@drawable/icon", Theme = "@style/MyTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)] 8 | public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity 9 | { 10 | protected override void OnCreate(Bundle bundle) 11 | { 12 | TabLayoutResource = Resource.Layout.Tabbar; 13 | ToolbarResource = Resource.Layout.Toolbar; 14 | 15 | base.OnCreate(bundle); 16 | 17 | Xamarin.Forms.Forms.Init(this, bundle); 18 | 19 | LoadApplication(new App()); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /samples/Plugin.FilePicker.Sample.Forms/Droid/Plugin.FilePicker.Sample.Forms.Droid.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {2A72EE4A-F43F-465D-BCAC-B953494B05CE} 7 | {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 8 | Library 9 | Plugin.FilePicker.Sample.Forms.Droid 10 | Plugin.FilePicker.Sample.Forms.Droid 11 | v10.0 12 | True 13 | Resources\Resource.designer.cs 14 | Resource 15 | Properties\AndroidManifest.xml 16 | Resources 17 | Assets 18 | 19 | 20 | PackageReference 21 | 22 | 23 | true 24 | full 25 | false 26 | bin\Debug 27 | DEBUG; 28 | prompt 29 | 4 30 | None 31 | 32 | 33 | true 34 | pdbonly 35 | true 36 | bin\Release 37 | prompt 38 | 4 39 | true 40 | false 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | {507fa967-a579-44fe-9ca3-7cee18b5257b} 51 | Plugin.FilePicker 52 | 53 | 54 | {bc539575-3b77-4a4a-8f3a-2203bb590674} 55 | Plugin.FilePicker.Sample.Forms 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 4.5.0.356 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /samples/Plugin.FilePicker.Sample.Forms/Droid/Properties/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /samples/Plugin.FilePicker.Sample.Forms/Droid/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using Android.App; 4 | 5 | // Information about this assembly is defined by the following attributes. 6 | // Change them to the values specific to your project. 7 | 8 | [assembly: AssemblyTitle("Plugin.FilePicker.Sample.Forms.Droid")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("")] 13 | [assembly: AssemblyCopyright("${AuthorCopyright}")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 18 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 19 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 20 | 21 | [assembly: AssemblyVersion("1.0.0")] 22 | 23 | // The following attributes are used to specify the signing key for the assembly, 24 | // if desired. See the Mono documentation for more information about signing. 25 | 26 | //[assembly: AssemblyDelaySign(false)] 27 | //[assembly: AssemblyKeyFile("")] 28 | -------------------------------------------------------------------------------- /samples/Plugin.FilePicker.Sample.Forms/Droid/Resources/AboutResources.txt: -------------------------------------------------------------------------------- 1 | Images, layout descriptions, binary blobs and string dictionaries can be included 2 | in your application as resource files. Various Android APIs are designed to 3 | operate on the resource IDs instead of dealing with images, strings or binary blobs 4 | directly. 5 | 6 | For example, a sample Android app that contains a user interface layout (main.axml), 7 | an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) 8 | would keep its resources in the "Resources" directory of the application: 9 | 10 | Resources/ 11 | drawable/ 12 | icon.png 13 | 14 | layout/ 15 | main.axml 16 | 17 | values/ 18 | strings.xml 19 | 20 | In order to get the build system to recognize Android resources, set the build action to 21 | "AndroidResource". The native Android APIs do not operate directly with filenames, but 22 | instead operate on resource IDs. When you compile an Android application that uses resources, 23 | the build system will package the resources for distribution and generate a class called "R" 24 | (this is an Android convention) that contains the tokens for each one of the resources 25 | included. For example, for the above Resources layout, this is what the R class would expose: 26 | 27 | public class R { 28 | public class drawable { 29 | public const int icon = 0x123; 30 | } 31 | 32 | public class layout { 33 | public const int main = 0x456; 34 | } 35 | 36 | public class strings { 37 | public const int first_string = 0xabc; 38 | public const int second_string = 0xbcd; 39 | } 40 | } 41 | 42 | You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main 43 | to reference the layout/main.axml file, or R.strings.first_string to reference the first 44 | string in the dictionary file values/strings.xml. 45 | -------------------------------------------------------------------------------- /samples/Plugin.FilePicker.Sample.Forms/Droid/Resources/drawable-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfversluis/FilePicker-Plugin-for-Xamarin-and-Windows/3604e0f259262616208929b29c5e3eb78466f9d0/samples/Plugin.FilePicker.Sample.Forms/Droid/Resources/drawable-hdpi/icon.png -------------------------------------------------------------------------------- /samples/Plugin.FilePicker.Sample.Forms/Droid/Resources/drawable-xhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfversluis/FilePicker-Plugin-for-Xamarin-and-Windows/3604e0f259262616208929b29c5e3eb78466f9d0/samples/Plugin.FilePicker.Sample.Forms/Droid/Resources/drawable-xhdpi/icon.png -------------------------------------------------------------------------------- /samples/Plugin.FilePicker.Sample.Forms/Droid/Resources/drawable-xxhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfversluis/FilePicker-Plugin-for-Xamarin-and-Windows/3604e0f259262616208929b29c5e3eb78466f9d0/samples/Plugin.FilePicker.Sample.Forms/Droid/Resources/drawable-xxhdpi/icon.png -------------------------------------------------------------------------------- /samples/Plugin.FilePicker.Sample.Forms/Droid/Resources/drawable/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfversluis/FilePicker-Plugin-for-Xamarin-and-Windows/3604e0f259262616208929b29c5e3eb78466f9d0/samples/Plugin.FilePicker.Sample.Forms/Droid/Resources/drawable/icon.png -------------------------------------------------------------------------------- /samples/Plugin.FilePicker.Sample.Forms/Droid/Resources/layout/Tabbar.axml: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /samples/Plugin.FilePicker.Sample.Forms/Droid/Resources/layout/Toolbar.axml: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /samples/Plugin.FilePicker.Sample.Forms/Droid/Resources/values/styles.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 5 | 6 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /samples/Plugin.FilePicker.Sample.Forms/Forms/App.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /samples/Plugin.FilePicker.Sample.Forms/Forms/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | 3 | namespace Plugin.FilePicker.Sample.Forms 4 | { 5 | public partial class App : Application 6 | { 7 | public App() 8 | { 9 | InitializeComponent(); 10 | 11 | MainPage = new MainPage(); 12 | } 13 | 14 | protected override void OnStart() 15 | { 16 | // Handle when your app starts 17 | } 18 | 19 | protected override void OnSleep() 20 | { 21 | // Handle when your app sleeps 22 | } 23 | 24 | protected override void OnResume() 25 | { 26 | // Handle when your app resumes 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /samples/Plugin.FilePicker.Sample.Forms/Forms/MainPage.xaml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 |