📜 ⬆️ ⬇️

Sending files to the Xamarin.Forms application. Part 1

File transfer between applications is a rather specific feature for the OS. And this is something that is better not to try to do in Xamarin.Forms, is not it? In fact, this is quite simple, and this post will demonstrate how to get this feature and run it in iOS (in the next post, the case with Android and, if necessary, with UWP will be considered).



This is a common practice of using mobile applications: opening a file in one application and the need to use another for further processing of this file. For example, you opened a PDF file, and there was a need to make some changes to this file in another application. When you tap on this PDF file, the “Open in” menu appears on the screen, allowing you to import this file into your preferred application.

It is worth noting that in this post we are not going to create an application extension to an iOS fragment of the Forms solution so that the application appears when the user taps the Share button (a small rectangle with an arrow going out of it). In this case, the file transfer to the Forms application will be considered, and not the exchange of content between applications.
')

Scenario


The example given in this post is an Xamarin.Forms application registered for the ability to open PDF files and then display them in WebView. Here will be considered the basics of registration for iOS, and therefore for Xamarin.Forms (This also applies to Android).

iOS registration


When I say that the Forms application will be registered, it means that it will work like these screenshots. Safari has a page with a PDF file.

The application is called “OpenForms”, and in the first screenshot, iOS provides the ability to directly open a file using the quick command “Open In OpenForms”.

In the second screenshot with a tap on the “More” menu, a window with a list of actions will appear below. Here is the shortcut of the desired application.

Info.plist


In order for iOS to understand that this application can process PDF files, you need to correct the Info.plist file. You need to add a new top-level key. You can do this with the built-in editor in Xamarin Studio or edit it directly.

To use Xamarin Studio, double-click on Info.Plist, and then the built-in editor will open. Select the “Advanced” tab at the bottom of the screen. In the “Document Types” section at the very top, click the “Add Document Type” button. This will add a section like the screenshot below.



So you need to fill it.
Name : Any name. It will be needed for reference later.
Types : This turns into an array of specific strings. More on this below.
Icons : The location of the shortcuts that will be displayed in the “More” menu, instead of the main application shortcut. Again, this can turn into an array of strings if there is more than one shortcut.

Filling in this way will change Info.plist and allow you to register the application to open other file types. But here it is necessary to understand in more detail to understand what is changing in Info.plist. It turns out that additional keys can be added to this file, which is not always possible in the IDE.

Here is the entire dictionary that was used to register the opening of files of the desired type.

<key>CFBundleDocumentTypes</key> <array> <dict> <key>CFBundleTypeName</key> <string>PDF</string> <key>CFBundleTypeRole</key> <string>Viewer</string> <key>LSHandlerRank</key> <string>Alternate</string> <key>LSItemContentTypes</key> <array> <string>com.adobe.pdf</string> </array> </dict> </array> 

CFBundleDocumentTypes is the key of the top-level dictionary, which in turn contains an array of other dictionary objects:


It's pretty simple, except for LSItemContentTypes . Where to get these values? For this purpose there is a Uniform Type Identifier. This is the string that identifies the file type. A list of publicly registered strings can be found on this Apple documentation page .

Now you need to understand how iOS lets the application know that there is a file waiting to open.

Response to open iOS events


When someone selects this application to open a PDF file, the following function is called:

 public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options) 

iOS copies the file to be opened by this application into the repository to which the application has access and which is specified using the NSUrl url parameter. Next, you need to process this file in Xamarin.Forms.

Then AppDelegate will look like this:

 App mainForms; public override bool FinishedLaunching(UIApplication app, NSDictionary options) { global::Xamarin.Forms.Forms.Init(); mainForms = new App(); LoadApplication(mainForms); return base.FinishedLaunching(app, options); } public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options) { mainForms.DisplayThePDF(url.Path); return true; } 

There are a couple of unusual moments here. First, the local variable Xamarin.Forms mainForms of the App class in AppDelegate is saved. You will need it later as an entry point to display the PDF.

Also, the DisplayPDF() function in the OpenUrl was called in the OpenUrl function. This will display the PDF in Xamarin.Forms. Ideally, you would need to copy the PDF and delete the source specified by the url parameter in order to clear the place. But not in this case.

Xamarin.Forms!


I spent a lot of time talking about iOS setup. However, when work begins in a real project, the iOS part is nothing more than a formality. The real work starts from the Xamarin.Forms side: how to process the incoming file. For this, I left a comment on the display of the PDF to the article I found on the Xamarin website . Here we talk about setting up the renderer.

Further, I would like to focus on the entry point to the Forms solution.

In the App.xaml.cs file or the App class (the class to which AppDelegate has access) there is a function that defines the interaction between iOS and Forms projects:

 public void DisplayThePDF(string url) { var openFilePage = new OpenFilesPage(url);; _navigationRoot.Navigation.PushModalAsync(new NavigationPage(openFilePage)); } 

This function creates a new Xamarin.Forms page, passes it the location of the file and displays this page modally (In the App class constructor, everything is nested in the NavigationPage and stored in the _navigationRoot variable).

Being displayed modally, it will appear on top of everything else that happens in the application, and will not affect the navigation stack in any way (except what appears on top). Of course, the orientation will be to view the PDF file. In a real application, you need to check the status of the application itself - what is being displayed at the moment (so that there is no stack of modal windows). The application workflow may require you to close the entire stack and start over or, if tabs are used, switch to a new one.

OpenFilesPage has a subclass of WebView with a custom renderer for each platform. In this class there is a property the location of the file to be displayed. Then the custom renderer displays it.
Displaying the file with a custom renderer will help to avoid moving to a specific location of the file in iOS. But again, this is only in this specific scenario execution. An important point is the need of the App class at the entry point to access the iOS project.

Total


In general, opening a file from an application in the Xamarin.Forms application is not that difficult. There are some formalities, one of which is to modify the Info.plist file in order to register the application as capable of handling files of a certain type. And the need to rewrite the OpenUrl function for an iOS application.

After that, it all depends on Xamarin.Forms. You must create an entry point in the App class so that the AppDelegate in iOS can refer to the “common” part of the code. Here you need to act depending on what needs to be done with the file. You may need to write a custom renderer to display. Or you can do everything in a general project, if you do not need additional platform functionality.

Thank you for the translation.


Alexander Alekseev - Xamarin-developer, freelancer. Works with the .NET platform since 2012. Participated in the development of a procurement automation system at Digamma. C 2015 went into freelancing and switched to mobile development using Xamarin. Currently working at StecPoint on an iOS application.

It manages the XamDev.ru resource and the Xamarin Developers community in social networks: VK , Facebook , Telegram .

Source: https://habr.com/ru/post/324138/


All Articles