1

I can not find a way how to open a file on Xamarin.Forms in Android from a dependency service.

By opening the file I mean showing the user the native UI to choose the which way he wants to open the file.

            XPlat.Storage.IStorageFile storageFile = await blob.GetContentFileAsync();
            File javaFile = new File(storageFile.Path);
            Plugin.CurrentActivity.ICurrentActivity activity = Plugin.CurrentActivity.CrossCurrentActivity.Current;
            Context context = activity.AppContext;
            Uri path = FileProvider.GetUriForFile(context, context.PackageName, javaFile);


            var intent = new Intent(Intent.ActionView);
            intent.AddFlags(ActivityFlags.NewTask);
            intent.AddFlags(ActivityFlags.GrantReadUriPermission);
            intent.AddFlags(ActivityFlags.ClearTop);
            string mimeType = MimeTypes.GetMimeType(System.IO.Path.GetExtension(blob.UniqueName));


            intent.SetDataAndType(path, mimeType);
            context.PackageManager.GetPackageInfo(context.PackageName, PackageInfoFlags.Activities);

            context.StartActivity(intent);

An exception is thrown when invoking the method StartActivity(intent)

Android.Content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=content://com.company.appname/root/data/data/com.company.appname/files/Blobs/file.pdf typ=application/pdf }

I also tried using different approach to get the Application context - var context = MonoAndroid.App.Application.Context;, but it seems like the context obtained through Plugin.CurrentActivity and this approach is the same.

Watch window screenshot


new edit

Commenting out the line intent.SetDataAndType(path, mimeType); results in following popup.

Popup

MBi
  • 51
  • 6
  • just use any of the normal .NET System.IO.File methods – Jason Jul 01 '19 at 13:55
  • I need the user to be presented with the dialog *Complete action using*. https://stackoverflow.com/questions/17165972/android-how-to-open-a-specific-folder-via-intent-and-show-its-content-in-a-file – MBi Jul 01 '19 at 14:13
  • @LucasZhang-MSFT sadly, I have not. I updated the original question. – MBi Jul 02 '19 at 09:28
  • Can you share a sample which contains the issue so that I can test it on my side. – Lucas Zhang Jul 02 '19 at 09:35
  • Turns out the problem is not in the activity / context. If I comment out the line `intent.SetDataAndType(path, mimeType);` it actually proceeds through and shows popup with three options: https://i.imgur.com/NJOiIop.png – MBi Jul 02 '19 at 09:59
  • @LucasZhang-MSFT I will try to create the sample later on. I updated the original question. Thank you for your help. – MBi Jul 02 '19 at 10:06
  • Yes I did, the problem was that no application was installed to handle desired mime type. – MBi Jul 15 '19 at 14:40

2 Answers2

1

It seems that you used the plugin CurrentActivityPlugin . Make sure you have installed it in MainActivity

protected override void OnCreate(Bundle savedInstanceState)
{
  TabLayoutResource = Resource.Layout.Tabbar;
  ToolbarResource = Resource.Layout.Toolbar;

  base.OnCreate(savedInstanceState);

  CrossCurrentActivity.Current.Init(this, savedInstanceState);
  Xamarin.Essentials.Platform.Init(this, savedInstanceState);
  global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
  LoadApplication(new App());
}

Android.Content.ActivityNotFoundException

This issue seems the app could not found the current Activity , so you can also use

Android.App.Application.Context

If the issue still appears , you can create a sample which contains the issue so that I can test it on my side.

Lucas Zhang
  • 18,630
  • 3
  • 12
  • 22
  • I have the content of the overriden method `OnCreate` same as yours. I will try the `Android.App.Application.Context` approach. – MBi Jul 02 '19 at 09:15
0

The problem was in a completely different thing. The device had no application installed that was able to handle the type of the file (application/pdf). Hovewer the exception that Android gives, gave me zero clues.

What I had to do, is check if user has appropriate app installed by calling intent.ResolveActivity(context.PackageManager).

Here is what I did:

Plugin.CurrentActivity.ICurrentActivity activity = Plugin.CurrentActivity.CrossCurrentActivity.Current;
Context context = activity.AppContext;

using (var intent = new Intent(Intent.ActionView))
{
    intent.SetDataAndType(path, mimeType);
    intent.AddFlags(ActivityFlags.NewTask);
    intent.AddFlags(ActivityFlags.GrantReadUriPermission);
    intent.AddFlags(ActivityFlags.ClearTop);

    ComponentName component = intent.ResolveActivity(context.PackageManager);
    // If the ResolveActivity returned null, we have no application installed
    // to handle our file type.
    if (component == null)
    {
        using (Toast toast = Toast.MakeText(context, new Java.Lang.String("No app installed to open this file."), ToastLength.Short))
        {
            toast.Show();
        }
        return false;
    }
    else
    {
        try
        {
            context.StartActivity(intent);
            return true;
        }
        catch (Exception ex)
        {
            Debug.WriteLine($"Failed to launch intent to open file. Exception message: {ex.Message}");
            using (Toast toast = Toast.MakeText(context, new Java.Lang.String("Can't open file."), ToastLength.Short))
            {
                toast.Show();
            }
            return false;
        }
    }
}
MBi
  • 51
  • 6