-2

I downloaded a PDF file as byte[] and save it into internal storage using File.WriteAllBytes(path, response);.

Now cannot access to it from android emulator, how could I save it on download folder? And what I need to be able to open it from pdf reader installed into emulator?

yensei
  • 1
  • 1
  • 4
  • Does this answer your question? [Xamarin.Forms save file (pdf) in local storage and open with the default viewer](https://stackoverflow.com/questions/60394507/xamarin-forms-save-file-pdf-in-local-storage-and-open-with-the-default-viewer) Please do some basic searching of the site for an existing post before asking a new question. – Ken White Jul 21 '21 at 03:14
  • I was searching, the thread you cite is specific for android, doesnt work for me. I need something works as multiplatform – yensei Jul 21 '21 at 03:47
  • Your post says *cannot access to it from android emulator*, which is Android specific. The post I linked answers the question you asked. – Ken White Jul 21 '21 at 03:51
  • the title says xamarin forms, I just make an example on android emulator – yensei Jul 21 '21 at 04:03

1 Answers1

0

how could I save it on download folder?

For android, you can save pdf file in download folder by following path.

  string rootPath = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Android.OS.Environment.DirectoryDownloads);

For ios, use this directory to store user documents and application data files.

var documents = Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments);

About open pdf in Anaroid, you can use the following code:

 public void openpdf()
    {
        string path = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Android.OS.Environment.DirectoryDownloads, "file.pdf");        
        // Get the uri for the saved file
        Android.Net.Uri file = Android.Support.V4.Content.FileProvider.GetUriForFile(MainActivity.mactivity, MainActivity.mactivity.PackageName + ".fileprovider", new Java.IO.File(path));
        Intent intent = new Intent(Intent.ActionView);
        intent.SetDataAndType(file, "application/pdf");
        intent.SetFlags(ActivityFlags.ClearWhenTaskReset | ActivityFlags.NewTask | ActivityFlags.GrantReadUriPermission | ActivityFlags.NewTask|ActivityFlags.NoHistory);
       
        try
        {
            MainActivity.mactivity.ApplicationContext.StartActivity(intent);              
        }
        catch (Exception)
        {
            Toast.MakeText(Xamarin.Forms.Forms.Context, "No Application Available to View PDF", ToastLength.Short).Show();
        }
    }

you need to add permission WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE in AndroidMainfeast.xml, then you also need to Runtime Permission Checks in Android 6.0.

private void checkpermission()
    {
        if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.WriteExternalStorage) == (int)Permission.Granted)
        {
            // We have permission, go ahead and use the writeexternalstorage.
        }
        else
        {
            // writeexternalstorage permission is not granted. If necessary display rationale & request.
            ActivityCompat.RequestPermissions(this, new String[] { Manifest.Permission.WriteExternalStorage }, 1);
        }
        if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.ReadExternalStorage) == (int)Permission.Granted)
        {
            // We have permission, go ahead and use the ReadExternalStorage.
        }
        else
        {
            // ReadExternalStorage permission is not granted. If necessary display rationale & request.
            ActivityCompat.RequestPermissions(this, new String[] { Manifest.Permission.ReadExternalStorage }, 1);
        }
    }

Also add a provider in the AndroidManifest.xml file:

    <application android:label="PdfSample.Android">
<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.companyname.fileprovider" android:exported="false" android:grantUriPermissions="true">
  <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"></meta-data>
</provider>
</application>

And add an external path in Resources/xml/file_paths.xml

<external-path name="external_files" path="."/>

MainActivity.mactivity is static property in MainActivity.cs:

 public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
    public static MainActivity mactivity;
    protected override void OnCreate(Bundle savedInstanceState)
    {
        TabLayoutResource = Resource.Layout.Tabbar;
        ToolbarResource = Resource.Layout.Toolbar;

        base.OnCreate(savedInstanceState);

        Xamarin.Essentials.Platform.Init(this, savedInstanceState);
        global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
        mactivity = this;

About open pdf in ios, you can take a look:

How to view PDF file using Xamarin Forms

Update:

My answer is also using DependencyService, you can create iterface in shared project.

public interface Iopenpdf
{
     void openpdf();
}

In Android platform, implement this interface.

[assembly: Xamarin.Forms.Dependency(typeof(openpdfhandle))]
namespace PdfSample.Droid
{
class openpdfhandle : Iopenpdf
{
    public void openpdf()
    {
        string path = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Android.OS.Environment.DirectoryDownloads, "file.pdf");
        //string path = Path.Combine(Android.App.Application.Context.GetExternalFilesDir(Environment.DirectoryDownloads).ToString(), "file.pdf");          
        // Get the uri for the saved file
        Android.Net.Uri file = Android.Support.V4.Content.FileProvider.GetUriForFile(MainActivity.mactivity, MainActivity.mactivity.PackageName + ".fileprovider", new Java.IO.File(path));
        Intent intent = new Intent(Intent.ActionView);
        intent.SetDataAndType(file, "application/pdf");
        intent.SetFlags(ActivityFlags.ClearWhenTaskReset | ActivityFlags.NewTask | ActivityFlags.GrantReadUriPermission | ActivityFlags.NewTask|ActivityFlags.NoHistory);
       
        try
        {
            MainActivity.mactivity.ApplicationContext.StartActivity(intent);              
        }
        catch (Exception)
        {
            Toast.MakeText(Xamarin.Forms.Forms.Context, "No Application Available to View PDF", ToastLength.Short).Show();
        }
    }
}
}

In shared code project, open pdf in button.click

 private void btnopen_Clicked(object sender, EventArgs e)
    {
        DependencyService.Get<Iopenpdf>().openpdf();
    }
Cherry Bu - MSFT
  • 10,160
  • 1
  • 10
  • 16
  • Thanks for your answer, really appreciate. After 3 days of research and test different solutions it seems to be a better implementations use `DependencyService` to make a specific implementation for each one. IOs, Droid, UWP. I am concerned about using specific Android libraries into shared project. – yensei Jul 21 '21 at 22:54
  • @yensei yes, my answer is also using [DependencyService](https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/dependency-service/introduction) to open pdf for each platform, about `DependencyService`, please see my update. – Cherry Bu - MSFT Jul 22 '21 at 01:24
  • Thanks Cherry. Need I some permissions for write my file into /storage/emulated/0/Download, I'm having `UnauthorizedAccessException` when I tried – yensei Jul 22 '21 at 01:30
  • @yensei yes, you need to add permission `WRITE_EXTERNAL_STORAGE` and `READ_EXTERNAL_STORAGE` in `AndroidMainfeast.xml`, then you also need to Runtime Permission Checks in Android 6.0. I mentioned in my reply. – Cherry Bu - MSFT Jul 22 '21 at 01:53
  • I learned a lot trying to make this work. Now I just need to open the pdf but I have `IllegalArgumentException` when reached openpdffile's method, message says `Failed to find configured root that contains /storage/emulated/0/Android/data/my.package/files/myfile.pdf`. I try with different folders to discard if that is the problem – yensei Jul 22 '21 at 03:27
  • My bad, I'm not updated my file_path.xml with dot as path. Thanks Cherry It worked now, just I need to test to others platforms and pray – yensei Jul 22 '21 at 03:52