'Xamarin.Android: Receive View and Send actions in an already running instance of an App (LaunchMode is SingleTop)

I want my app to be a viewer and send target for PDFs but don't want it to create new instances everytime. How do I catch the view intent action in my MainActivity? I tried OnNewIntent() but it doesn't get called. Only if the app wasn't already running, I get the action in OnCreate(). What am I missing?

[Activity (Theme = "@style/MainTheme", Label = "MyPdfViewer", Icon = "@drawable/icon", /*MainLauncher = true, --> SplashActivity is now the MainLauncher */LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
[IntentFilter(new[] { Intent.ActionSend }, Categories = new[] { Intent.CategoryDefault }, DataMimeType = @"application/pdf")]
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, DataMimeType = @"application/pdf")]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);

        LoadApplication (new App ());

        // handle clipboard data "send to" or "view document" actions
        if (Intent.Type == "application/pdf")
        {
            HandleSendOrViewAction();
        }

    }

    protected virtual void OnNewIntent()
    {
        var data = this.Intent.Data;  // <-- never called
        // do similar thing like in HandleSendOrViewAction()
    }

    private bool HandleSendOrViewAction()
    {
        // Get the info from ClipData 
        var pdf = Intent.ClipData.GetItemAt(0);

        // Open a stream from the URI 
        byte[] bytes;
        Stream inputStream;
        if (Intent.Action == Intent.ActionSend)
            inputStream = ContentResolver.OpenInputStream(pdf.Uri);
        else if (Intent.Action == Intent.ActionView)
            inputStream = ContentResolver.OpenInputStream(Intent.Data);
        else
            return false;

        using (StreamReader sr = new StreamReader(inputStream))
        {
            MemoryStream ms = new MemoryStream();
            inputStream.CopyTo(ms);
            bytes = ms.ToArray();
        }

        Services.PdfReceiver.Base64Data = Convert.ToBase64String(bytes);  

        return true;
    }


Solution 1:[1]

but don't want it to create new instances everytime.

The standard and singleTop of Launch Mode would create multiple instances. if you do not want create instance every time, you could use singleTask and singleInstance instead.

For singleTop Launch Mode, you need to know, if an instance of the activity already exists at the top of the target task, the system routes the intent to that instance through a call to its onNewIntent() method, rather than creating a new instance of the activity. If the instance of the activity which already exists is not at the top, it would not call onNewIntent() method.

That's why i suggest to use singleTask. The system creates the activity at the root of a new task and routes the intent to it. However, if an instance of the activity already exists, the system routes the intent to existing instance through a call to its onNewIntent() method, rather than creating a new one.

Solution 2:[2]

Using SingleTop launch mode is correct. The reason that OnNewIntent() is not being called is that you have declared it like this:

protected virtual void OnNewIntent()

That isn't correct. The signature is wrong. You need to declare it like this:

protected override void OnNewIntent(Intent intent)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Wendy Zang - MSFT
Solution 2 David Wasser