0

I am working in a xmarin android app in c#. I want to open a pdf file which is in a custom folder of internal storage "TESTFOLDER". code is given below, every time it is going to the catch section whiche it is going to start the activity. how to open it? enter image description here

code

var externalPath = global::Android.OS.Environment.ExternalStorageDirectory.Path + "/TESTFOLDER";
                Java.IO.File file = new Java.IO.File(externalPath, "qdummy.pdf");
                if(file.Exists())
                {
                    try
                    {
                        file.SetReadable(true);
                        Android.Net.Uri uri = Android.Net.Uri.FromFile(file);
                        Intent intent = new Intent(Intent.ActionView);
                        intent.SetDataAndType(uri, "application/pdf");
                        intent.SetFlags(ActivityFlags.ClearWhenTaskReset | ActivityFlags.NewTask);                        
                        intent.SetFlags(ActivityFlags.NoHistory);
                        StartActivity(intent);                        
                    }
                    catch (Exception ex)
                    {
                        Toast.MakeText(Application.Context, "problem", ToastLength.Long).Show();
                    }
                }
                else
                {
                    Toast.MakeText(Application.Context, "No exx", ToastLength.Long).Show();
                }
Osama Raddad
  • 344
  • 3
  • 17
Soumen Halder
  • 117
  • 1
  • 13
  • Hope this helps. https://stackoverflow.com/questions/12194912/open-file-picker-form-my-android-activity – Sathish Guru V Feb 14 '20 at 12:34
  • Does this answer your question? [How to open a PDF via Intent from SD card](https://stackoverflow.com/questions/10530416/how-to-open-a-pdf-via-intent-from-sd-card) – Martheen Feb 14 '20 at 12:53
  • Which exception are you getting? – Cheesebaron Feb 16 '20 at 08:00
  • @Cheesebaron the error is `Java.Lang.Exception: file:///storage/emulated/0/TESTFOLDER/qdummy.pdf exposed beyond app through Intent.getData() at System.Runtime.ExceptionServices.ExceptionDispatchInfo`... – Soumen Halder Feb 17 '20 at 05:14
  • Same Issue is solved in this post. It Saves my day https://stackoverflow.com/questions/60394507/xamarin-forms-save-file-pdf-in-local-storage-and-open-with-the-default-viewer – Muneeb Ur Rehman Aug 17 '20 at 21:56

2 Answers2

0

According to your description and error message, you need to wrap your URI with FileProvider. Since android uri will give you file:// while FileProvider will give you content:// firstly.

 Android.Net.Uri pdfPath = FileProvider.GetUriForFile(context, context.ApplicationContext.PackageName + ".provider", file);

then you need to add FileProvider to your manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.pdfsample" android:installLocation="auto">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme">
    <provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.provider" android:exported="false" android:grantUriPermissions="true">
        <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" />
    </provider>
</application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
</manifest>

You also need to create Resources\xml folder with file_paths.xml

<?xml version="1.0" encoding="utf-8" ?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
 <external-files-path name="root" path="."/>
 <external-files-path name="files" path="files" />
 <external-path name="external_files" path="."/>
</paths>

Open pdf code:

 var externalPath = global::Android.OS.Environment.ExternalStorageDirectory.Path + "/testfolder";
        Java.IO.File file = new Java.IO.File(externalPath, "test.pdf");
        if(file.Exists())
        {
            var context = Android.App.Application.Context;
            try
            {

                Android.Net.Uri pdfPath = FileProvider.GetUriForFile(context, context.ApplicationContext.PackageName + ".provider", file);
                context.GrantUriPermission(context.PackageName, pdfPath, ActivityFlags.GrantReadUriPermission);
                Intent intent = new Intent();
                intent.SetFlags(ActivityFlags.GrantReadUriPermission);
                intent.SetAction(Android.Content.Intent.ActionView);
                intent.SetFlags(ActivityFlags.NoHistory);
                intent.SetFlags(ActivityFlags.ClearWhenTaskReset | ActivityFlags.NewTask);
                intent.SetDataAndType(pdfPath, "application/pdf");
                context.StartActivity(intent);

            }
            catch (Exception ex)
            {
                Toast.MakeText(Application.Context, "problem", ToastLength.Long).Show();
            }

        }

Here is the same thread that you can take a look:

How do I open an internally created pdf in Xamarin.Android via a FileProvider in the default system pdf app?

Cherry Bu - MSFT
  • 10,160
  • 1
  • 10
  • 16
  • Thanks for replying @Cherry Bu - MSFT , I just copy and pest your code into my MainActivity.cs, it is now asking users to open pdf with preferred apps installed in mobile, I have 3 options present in my mobile to open a pdf, i) wps office ii) Drive PDF viewer iii)Adobe Acrobat Reader.After opening wps office -- it is saying "wps office is determining the type of document" and PDF is not showing. In Drive PDF viewer-- after opening it is showing nothing. and in acrobat reader-- it is saying "file colud not be accessed. check your location" but the pdf is present in the correct location. – Soumen Halder Feb 17 '20 at 09:49
  • Here I am using minSdkVersion="19" and targetSdkVersion="27" , the test pdf is normally opening from external storage folder through i) wps office ii) Drive PDF viewer iii)Adobe Acrobat Reader apps. Is there else which I am missing. please help @Cherry Bu - MSFT – Soumen Halder Feb 17 '20 at 12:32
  • @Soumen Please wait a minute, I will test it at my side to choose pdf viewer. – Cherry Bu - MSFT Feb 18 '20 at 09:39
  • dear @Cherry Bu - MSFT issue is resolved. I have provided the answer in the answer section. – Soumen Halder Feb 18 '20 at 09:56
0

issue has been resolved,

** please follow all the steps written in this blog, just replace the try catch block to resolve the issue.

try
                    {
                        string extension = MimeTypeMap.GetFileExtensionFromUrl(Android.Net.Uri.FromFile(file).ToString());
                        string mimeType = MimeTypeMap.Singleton.GetMimeTypeFromExtension(extension);
                        Intent intent = new Intent(Intent.ActionView);
                        intent.SetFlags(ActivityFlags.ClearTop | ActivityFlags.NewTask);
                        Android.Net.Uri path = FileProvider.GetUriForFile(Application.Context, Android.App.Application.Context.PackageName + ".provider", file);
                        intent.SetDataAndType(path, mimeType);
                        intent.AddFlags(ActivityFlags.GrantReadUriPermission);
                        Application.Context.StartActivity(Intent.CreateChooser(intent, "Choose App"));
                    }
                    catch (Exception ex)
                    {
                        Toast.MakeText(Application.Context, "problem", ToastLength.Long).Show();
                    }
Soumen Halder
  • 117
  • 1
  • 13