How to open IMAGE and PDF from Local Storage in Xamarin.Forms ?

How to open IMAGE and PDF from Local Storage in Xamarin.Forms ?

Opening IMAGE and PDF from Local Storage in Xamarin.Forms


Today, we are going to learn about, Opening Image and PDF files from local storage in Xamarin.Forms.  When we are trying to open files from local storage in Xamarin.Forms,  then we need to write code platform specific because different platforms have different implementation.


Let's Code:

Before start code please read about DependencyService From Xamarin Official Site.

Step 1: Create Xamarin.Forms Project in Visual Studio 2019

opening image from local storage in xamarin forms project

 Select App from Multiplatform option then click on Blank Forms App Click on Next

Step 2: Give name to project and select project location

project creation in xamarin forms

Step 3: Open MainPage.xaml to add two buttons

<?xml version="1.0" encoding="utf-8"?>
<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:TestFiles_XF"
    x:Class="TestFiles_XF.MainPage">
    <StackLayout
        Padding="20"
        VerticalOptions="CenterAndExpand">
        <Button
            Text="Open Image"
            Clicked="OpenImage_Clicked"
            TextColor="Blue"
            FontAttributes="Bold"
            BackgroundColor="White"
            BorderColor="Blue"
            BorderWidth="1" />
        <Button
            Text="Open PDF"
            Clicked="OpenPDF_Clicked"
            TextColor="Blue"
            FontAttributes="Bold"
            BackgroundColor="White"
            BorderColor="Blue"
            BorderWidth="1" />
    </StackLayout>
</ContentPage>



Step 4: Add Storage permission into manifest file in android project.


Step 5: Create Interface in PCL project.

namespace TestFiles_XF.Interface
{
    public interface IOpenFile
    {
        void OpenFile(string filePath);
    }
}

Step 6 : Implement interface into Android Project.

Before implement interface into android we need add  FileProvider ,

So create xml Folder into Resource folder,


add provider_paths.xml file into xml folder

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

Specify fileprovider into manifest file

    <application android:label="TestFiles_XF.Android">
        <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/provider_paths" />
        </provider>
    </application>
  
Let's implement interface for open local image and pdf file,


Create class OpenFiles.cs class and implement IOpenFile interface, like below

[assembly: Dependency(typeof(OpenFiles))]
namespace TestFiles_XF.Droid.Services
{
    public class OpenFiles: IOpenFile
    {
        public OpenFiles()
        {
        }

        public void OpenFile(string path)
        {
            
var localFile = new Java.IO.File(path);   // getting files from path

            var uri = FileProvider.GetUriForFile(MainActivity.Current, "com.demo.testfiles_xf.provider", localFile);

            Intent intent = new Intent(Intent.ActionView);
            intent.SetFlags(ActivityFlags.ClearWhenTaskReset | ActivityFlags.NewTask);
            var extension = MimeTypeMap.GetFileExtensionFromUrl(path);
            var mimeType = MimeTypeMap.Singleton.GetMimeTypeFromExtension(extension.ToLower());
            intent.AddFlags(ActivityFlags.GrantReadUriPermission);
            intent.SetDataAndType(uri, mimeType); 
            MainActivity.Current.StartActivity(intent);
  

        
    }

}


Step 7 : Create OpenFiles.cs class into iOS project to implement IOpenFIle interface

We will use QLPreviewItem class to preview files for that you need to implement this abstract class 

    public class PreviewFile : QLPreviewItem
    {
        string filepath;
        string filename;
        public PreviewFile(string fileName, string filePath)
        {
            this.filepath = filePath;
            this.filename = fileName;
        }
        public override string ItemTitle
        {
            get
            {
                return filename;
            }
        }

        public override NSUrl ItemUrl
        {
            get
            {
                return NSUrl.FromFilename(filepath);
            }
        }
    }


Then, 
we will use QLPreviewController for preview 
controller. for QLPreviewController we need to implement 
QLPreviewControllerDataSource Abstract Class :

 public class PreviewControllerDataSource:QLPreviewControllerDataSource
    {
        private QLPreviewItem _item;
        public PreviewControllerDataSource(QLPreviewItem item)
        {
            _item = item;
        }

        public override IQLPreviewItem GetPreviewItem(QLPreviewController controller, nint index)
        {
            return _item;
        }

        public override nint PreviewItemCount(QLPreviewController controller)
        {
            return 1;
        }
    }

Let's implement IOpenFile Interface for preview file implementation

[assembly: Dependency(typeof(OpenFiles))]
namespace TestFiles_XF.iOS.Services
{
    public class OpenFiles : IOpenFile
    {
        public void OpenFile(string filePath)
        {
            string fileName = "test";
            string ext = string.Empty;
            if (filePath.Contains(".pdf"))
            {
                ext = ".pdf";
            }
            else
            {
                ext = ".png";
              
            }
            PreviewFile previewFile = new PreviewFile(fileName+ext, filePath);
            QLPreviewController previewController = new QLPreviewController();
            previewController.DataSource = new PreviewControllerDataSource(previewFile);
            UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(previewController, true, HandleAction);

        }

        void HandleAction()
        {

        }
    }
}


Finally we implemented interface (platform specific code), let's test, 
We have two buttons 
1. Open Image -->OpenImage_Clicked()
2. Open PDF -->OpenPDF_Clicked()

       async void OpenImage_Clicked(object sender, System.EventArgs e)
        {
            await RequestPermission();
            string imagePath = "Put here local file path";  
                         DependencyService.Get<IOpenFile>().OpenFile(imagePath);
        }

        async void OpenPDF_Clicked(object sender, System.EventArgs e)
        {
            await RequestPermission();
            string pdfPath = "
Put here local file path";
            DependencyService.Get<IOpenFile>().OpenFile(pdfPath);
        }



Here we used RequestPermission() for permissions.

 async Task RequestPermission()
 {
  var res = await Plugin.Permissions.CrossPermissions.Current.CheckPermissionStatusAsync(
  Plugin.Permissions.Abstractions.Permission.Storage);
 if (res == Plugin.Permissions.Abstractions.PermissionStatus.Granted)
   return;
else
   {
              await Plugin.Permissions.CrossPermissions.Current.RequestPermissionsAsync(
             Plugin.Permissions.Abstractions.Permission.Storage);

   }
 }

Read More :


Result's :










How to open IMAGE and PDF from Local Storage in Xamarin.Forms ? How to open IMAGE and PDF from Local Storage in Xamarin.Forms ? Reviewed by Dev Tech Solution on July 21, 2019 Rating: 5

9 comments:

  1. Replies
    1. just define static instance of your main activity like below,
      public static MainActivity Current =null;

      MainActivity()
      {
      Current=this;
      }

      Delete
  2. Woah!! Such a piece of the nice information you have shared here, I have read the entire post and I must say that the information is very helpful for me.
     Xamarin Development Company texas

    ReplyDelete
  3. Hi. Thanks for this. It's a very good post. When testing in android emulator and try to open a PDF document in downloads folder, recive an error "Object reference not set to an instance of an object" executing de sentence "DependencyService.Get().OpenFile(documentPath);".

    Can you help me, to resolve?

    ReplyDelete
    Replies
    1. Hi,
      Did you register your DependencyService--> [assembly: Dependency(typeof(OpenFiles))]

      Delete
  4. Thanks for answering.

    I had a problem in the dependency registry and when correcting it, the application work. I published it in the Google store. Now when I download it, everything works fine until I try to view a document. At that time the application is broken and closed.

    Any idea? I need to activate the app as soon as possible.

    ReplyDelete
  5. I think you have problem in FileProvider,
    check below link it will help ..
    https://github.com/xamarin/Essentials/issues/130

    ReplyDelete
  6. hi, i got this exception

    Java.Lang.NullPointerException: 'Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference'

    how to resolve this ,

    ReplyDelete
    Replies
    1. I also have the same problem. Had you solved it?

      Delete

Powered by Blogger.