How to open 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
|
Step 2: Give name to project and select project location
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);
}
}
{
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>
<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
<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>
</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);
}
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);
}
}
}
{
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;
}
}
{
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
{
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";
{
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);
}
}
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(
{
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(
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 ?
Reviewed by Dev Tech Solution
on
July 21, 2019
Rating:
MainActivity.Current not found
ReplyDeletejust define static instance of your main activity like below,
Deletepublic static MainActivity Current =null;
MainActivity()
{
Current=this;
}
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.
ReplyDeleteXamarin Development Company texas
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);".
ReplyDeleteCan you help me, to resolve?
Hi,
DeleteDid you register your DependencyService--> [assembly: Dependency(typeof(OpenFiles))]
Thanks for answering.
ReplyDeleteI 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.
I think you have problem in FileProvider,
ReplyDeletecheck below link it will help ..
https://github.com/xamarin/Essentials/issues/130
hi, i got this exception
ReplyDeleteJava.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 ,
I also have the same problem. Had you solved it?
Delete