For the majority of the apps I’ve worked on, there’s been a requirement to store some sort of data in files. Whether it’s images from the camera or gallery, a database or just log files it seems to come up more often than not.
When you’re working in the simulator/emulator environment during development it’s not too difficult to get access to these files so you can interrogate them and work on things from there.
When your app is in the hands of testers, or even actual users, this isn’t such a simple thing.
An approach I’ve been using for a while now (and often this is just in test builds on a screen “Developer Settings” or something) is to have an option to zip everything I want up to help with debugging and then having the user share it, whether that’s via email or Skype or whatever.
This used to be a bit more complicated in the days of PCL’s and Shared Projects that required platform specific implementations of the various parts, but with .NET Standard and a little bit of help from Xamarin.Essentials, this is now a breeze.
Once you’ve added the utility method, incorporating this functionality in your app is as simple as:
1 |
await Utilities.ExportUtilties.CompressAndExportFolder(dataPath); |
There is some fiddling around with where the files are and setting the temporary paths, but to actually zip things up it’s just a matter of:
1 2 3 4 5 6 7 |
using System.IO.Compression; ... ZipFile.CreateFromDirectory(folderPath, exportZipFilePath, CompressionLevel.Fastest, true); ... |
Then just add the Xamarin.Essentials NuGet* package to all projects and to present the user a standard share dialog on each platform with the zip file just created is as simple as:
1 2 3 4 5 6 7 8 9 10 11 |
using Xamarin.Essentials; ... await Share.RequestAsync(new ShareFileRequest { Title = "My App Data", File = new ShareFile(exportZipFilePath), }); ... |
* Note: If you’re using a version of Xamarin.Essentials < 1.3.0 then you’ll also need to add the following code to your App.xaml.cs or App.cs during initialisation:
1 2 3 4 5 6 7 |
using Xamarin.Essentials; ... ExperimentalFeatures.Enable(ExperimentalFeatures.ShareFileRequest); ... |
The full source code of the utility is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
using System; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Threading.Tasks; using Xamarin.Essentials; namespace ZipAndShareExample.Utilities { public static class ExportUtilties { public static async Task CompressAndExportFolder(string folderPath) { // Get a temporary cache directory var exportZipTempDirectory = Path.Combine(FileSystem.CacheDirectory, "Export"); // Delete folder incase anything from previous exports, it will be recreated later anyway try { if (Directory.Exists(exportZipTempDirectory)) { Directory.Delete(exportZipTempDirectory, true); } } catch (Exception ex) { // Log things and move on, don't want to fail just because of a left over lock or something Debug.WriteLine(ex); } // Get a timestamped filename var exportZipFilename = $"MyAppData_{DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss")}.zip"; Directory.CreateDirectory(exportZipTempDirectory); var exportZipFilePath = Path.Combine(exportZipTempDirectory, exportZipFilename); if (File.Exists(exportZipFilePath)) { File.Delete(exportZipFilePath); } // Zip everything up ZipFile.CreateFromDirectory(folderPath, exportZipFilePath, CompressionLevel.Fastest, true); // Give the user the option to share this using whatever medium they like await Share.RequestAsync(new ShareFileRequest { Title = "My App Data", File = new ShareFile(exportZipFilePath), }); return true; } } } |
This is a nice and succinct way of wrapping some files and exporting them so you can see what’s happening on the users actual device and app set up rather than trying to guess and facing the old cliché: works on my machine.
I hope this is helpful for some of you. As I mentioned, I add a basic Developer Settings screen in most apps I work on (one day I might even write about it and share a sample you can just drop in, if there’s ever time…) as they get more complex and add this in as a way for users to just send through a snapshot of their environment so I can then further work through what they’re doing.
You can even get more complicated and change the above to actually import their data into the app (there’s extract functionality within the ZipeFile class) directly to your device and run their scenario up for yourself.
If you want the entire working example, please have a look here on GitHub.
Leave A Comment