Forum Xamarin.Forms
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

Open file from gmail application

guizmoguizmo Member ✭✭
edited August 8 in Xamarin.Forms

Hi,

I'am trying to open a pdf file from other apps. Howewer from email attachment it doesn't work, my cursor is returning null.

Here is my code used to open file from intent.

  `public class IntentHelper
   {
    private readonly MainActivity mainActivity;

    public IntentHelper(MainActivity mainActivity)
    {
        this.mainActivity = mainActivity;
    }

    public void GetFilePathFromIntent()
    {
        if (Intent.ActionView.Equals(mainActivity.Intent.Action) && (mainActivity.Intent.Type?.Equals("application/pdf") ?? false))
        {
            var path = GetRealPathFromUri(Android.App.Application.Context, mainActivity.Intent.Data);

            //TODO -- Implement try catch
            App.LoadPdf(path);
        }
    }

    public static string GetRealPathFromUri(Context context, Android.Net.Uri uri)
    {

        bool isKitKat = Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Kitkat;

        // DocumentProvider
        if (isKitKat && Android.Provider.DocumentsContract.IsDocumentUri(context, uri))
        {
            // ExternalStorageProvider
            if (IsExternalStorageDocument(uri))
                return GetExternalStorageDocument(uri);
            // DownloadsProvider
            else if (IsDownloadsDocument(uri))
                return GetDownloadDirectory(context, uri);
            // MediaProvider
            else if (IsMediaDocument(uri))
                return GetMediaDirectory(context, uri);
        }
        // MediaStore (and general)
        else if ("content".Equals(uri.Scheme, StringComparison.OrdinalIgnoreCase))
        {
            return GetDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".Equals(uri.Scheme, StringComparison.OrdinalIgnoreCase))
        {
            return uri.Path;
        }

        return null;
    }

    public static bool IsExternalStorageDocument(Android.Net.Uri uri)
    {
        return "com.android.externalstorage.documents".Equals(uri.Authority);
    }

    private static string GetExternalStorageDocument(Uri uri)
    {
        var docId = Android.Provider.DocumentsContract.GetDocumentId(uri);
        var split = docId.Split(':');
        var type = split[0];

        return "primary".Equals(type, StringComparison.OrdinalIgnoreCase)
            ? Android.OS.Environment.ExternalStorageDirectory + "/" + split[1]
            : null;
    }

    private static bool IsDownloadsDocument(Android.Net.Uri uri)
    {
        return "com.android.providers.downloads.documents".Equals(uri.Authority);
    }

    private static string GetDownloadDirectory(Context context, Uri uri)
    {
        var id = Android.Provider.DocumentsContract.GetDocumentId(uri);
        var contentUri = ContentUris.WithAppendedId(Android.Net.Uri.Parse("content://downloads/public_downloads"),
            Convert.ToInt64(id));

        return GetDataColumn(context, contentUri, null, null);
    }

    private static bool IsMediaDocument(Android.Net.Uri uri)
    {
        return "com.android.providers.media.documents".Equals(uri.Authority);
    }

    private static string GetMediaDirectory(Context context, Uri uri)
    {
        var docId = Android.Provider.DocumentsContract.GetDocumentId(uri);
        var split = docId.Split(':');
        var type = split[0];

        Uri contentUri = type switch
        {
            "image" => Android.Provider.MediaStore.Images.Media.ExternalContentUri,
            "video" => Android.Provider.MediaStore.Video.Media.ExternalContentUri,
            "audio" => Android.Provider.MediaStore.Audio.Media.ExternalContentUri,
            _ => null
        };

        const string selection = "_id=?";
        var selectionArgs = new string[]
        {
            split[1]
        };

        return GetDataColumn(context, contentUri, selection, selectionArgs);
    }

    public static string GetDataColumn(Context context, Android.Net.Uri uri, String selection,
        string[] selectionArgs)
    {
        Android.Database.ICursor cursor = null;
        const string column = "_data";
        string[] projection = {
            column
        };

        try
        {
            cursor = context.ContentResolver.Query(uri, projection, selection, selectionArgs,
                null);
            if (cursor != null && cursor.MoveToFirst())
            {
                var column_index = cursor.GetColumnIndexOrThrow(column);
                return cursor.GetString(column_index);
            }
        }
        finally
        {
            cursor?.Close();
        }

        return null;
    }
}`

If I try to open a document from the file explorer it will work. Howewer If the document isn't stored initially in the device I cannot get the uri.

I try to use Intent.ActionView or Intent.ActionOpenDocument but it doesn't work.

Any tips ?

Sign In or Register to comment.