📜 ⬆️ ⬇️

Sending files to the Xamarin.Forms application. Part 2

Last week we talked about sending files to the Xamarin.Forms application for iOS, as promised, in the second part we’ll talk about Android.



Sending files to the Xamarin.Forms application: part 1 (iOS) and part 2 (Android) .

Scenario


Again the script that will be discussed:
')

Let's get started

Registration in Android


Also, as the Intents are used to exchange data between the components of an Activity, you can use the Intents for the same between applications.

Explicit and implicit intentions


When it is clear which Activity component to open in the application, you need to create an explicit Intent. When an explicit Intent is created, it indicates the class type of the Activity component to be started, then the OS starts working when it finds StartActivity ().

Simple enough. But what happens when the developer of the source application does not know which component of the Activity should be launched, since this component of the Activity is in a separate application? The application “sends” a notification that there is something that needs to be delivered to another application and “asks” if it can perform an action on it.

This is where the implicit Intent comes in. The developer creates an implicit Intent without specifying the Activity component to be started.

However, the implicit Intent still needs enough information for the Android OS to determine which application should receive the information. The creation of implicit intentions will not be considered here, but only their application. This article is about Intentations in detail.

Intent filters


All information about explicit and implicit Intente leads to the concept of Intent-filters. Intent filters are the way in which an application that receives a file is registered with Android to process incoming data.

Intent filters are associated with the Activity components in the application, which should start when the file is received. The description of the content filter appears in the AndroidManifest.xml file along with a description for the Activity component.

To determine which application will be launched and displayed in options, when a user sends a file of a certain type to another application, Android “scans” all Intent filters registered by the OS and filters applications based on the principle of comparing criteria of Intent filters with criteria declared in implicit Intent 'e.

How to create an intent filter?

Intent filter declaration


As noted, a description of the Intent filter appears along with a description of the Activity component, which should be launched when a file is received.

An example of declaring the Activity component and the Intent filter in the AndroidManifest.xml file is as follows:

<activity android:configChanges="orientation|screenSize" android:icon="@drawable/icon" android:label="OpenFiles.Droid" android:theme="@style/MyTheme" android:name="md5d37a78bf190038b83be9873b4223f8d1.MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.SEND" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="application/pdf" /> </intent-filter> </activity> 

Here it is necessary to note a couple of points. The first is that one Activity component can have more than one Inent filter. The second is the keywords included in the <intent-filter> node. These keywords help Android filter out applications that can perform certain operations. Here is an explanation of the values ​​in this case of receiving the file:


This completes the work with the Android part. The time has come for a Xamarin.Forms application.

Integration with Xamarin.Forms


First you need to understand how to add an Intent filter to the Android part of the Xamarin.Forms application. Xamarin provides many tools, so there is no need to touch the AndroidManifest.xml file often. If you need to add a value in this file, you can refer to the visual designer (by double-clicking the file) or to various class attributes.

It so happens that Intent-filters can be added using the IntentFilterAttribute class. Since there is only one Activity component in a Forms application, you need to MainActivity class with this attribute. To generate the XML in the AndroidManifest.xml file, identical to the one described above, the declaration of the MainActivity class should look like this:

 [Activity(Label = "OpenFiles.Droid", Icon = "@drawable/icon", Theme = "@style/MyTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)] [IntentFilter(new[] { Intent.ActionSend }, Categories = new[] { Intent.CategoryDefault }, DataMimeType = @"application/pdf")] public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity { 

There is also an ActivityAttribute class that will create an Activity node in the manifest. Then the IntentFilterAttribute class adds an Intent filter to this Activity node. Full documentation on the IntentFilterAttribute class can be found here . It defines the action, category and type of incoming data. Action and category are arrays, and they can be defined. They may also contain parameters that help filter by matching criteria. With this add-on, the Android class recognizes an application as capable of handling PDF files.

Processing incoming file


Now that the application has been identified by Android as appropriate, it is necessary to consider the situation when something falls into it.

When a file arrives, the OnCreate function in the MainActivity . The Activity Intent property contains information that is needed to get the base file. While retrieving the file, you can expect the necessary information in the ClipData object of the ClipData property.

This information is Android.Net.Uri , which is used by ContentResolver to start the data stream. You can then save this data stream in the application as a local file.

Depending on the application sending the data, you can also view the URI of the file being sent to Extras Intent - Intent.ExtraStream .

Regardless of where Uri received from, it is necessary to make sure that the file is saved in the application. In this case, there will be confidence that the file will have full access.

The entire OnCreate shown below.

 App _mainForms; protected override void OnCreate(Bundle bundle) { TabLayoutResource = Resource.Layout.Tabbar; ToolbarResource = Resource.Layout.Toolbar; base.OnCreate(bundle); global::Xamarin.Forms.Forms.Init(this, bundle); var mainForms = new App(); LoadApplication(mainForms); if (Intent.Action == Intent.ActionSend) { //     Extras var uriFromExtras = Intent.GetParcelableExtra(Intent.ExtraStream) as Android.Net.Uri; var subject = Intent.GetStringExtra(Intent.ExtraSubject); //    ClipData var pdf = Intent.ClipData.GetItemAt(0); //    URI var pdfStream = ContentResolver.OpenInputStream(pdf.Uri); //  var memOfPdf = new System.IO.MemoryStream(); pdfStream.CopyTo(memOfPdf); var docsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal); var filePath = System.IO.Path.Combine(docsPath, "temp.pdf"); System.IO.File.WriteAllBytes(filePath, memOfPdf.ToArray()); mainForms.DisplayThePDF(filePath); } } 

This is the usual Xamarin.Forms OnCreate . The significant difference is that after calling Xamarin.Forms LoadApplication , it checks if the Intent was loaded with information from another application, causing the implicit Intent.

If it finds data in the Intent property that receives the Intent.ActionSend action (that is, the file is sent to the application), the file is copied to the application's local storage, then the DisplayThePDF() function is DisplayThePDF() .

DisplayThePDF() displays a modal page in a web browser, and this web browser displays the downloaded PDF file. This browser works through a custom renderer. The code for this renderer is written using the Xamarin documentation .

When done, the Android application will display the PDF files as in the image on the right.

Total


In general, having understood how Android communicates data between applications, which is similar to exchanging data between Activity components in a single application, the task of getting files to Android becomes easily solvable. You must declare an Intent filter in the MainActivity class in an Android project in Xamarin.Forms using the IntentFilterAttribute . After that, the corresponding markup is placed in the AndroidManifest.xml file, and now all you need to do is to process the incoming data using the OnCreate() function, which ideally will simply transfer the work of the function already in the Xamarin.Forms project.

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/324796/


All Articles