I have a pdf i\'ve added as an AndroidAsset and a BundleResource for my Android and IOS projects using xamarin forms.
I just want to be able to open those files from any
First of all you will need an interface class, since you need to call the dependency service in order to pass your document to the native implementation(s) of your app:
so in your shared code add an interface, called "IDocumentView.cs":
public interface IDocumentView
{
void DocumentView(string file, string title);
}
Android
Now in your android project create the corresponding implementation "DocumentView.cs":
assembly: Dependency(typeof(DocumentView))]
namespace MyApp.Droid.Services
{
public class DocumentView: IDocumentView
{
void IDocumentView.DocumentView(string filepath, string title)
{
try
{
File file = new File(filepath);
String mime = FileTypes.GetMimeTypeByExtension(MimeTypeMap.GetFileExtensionFromUrl(filepath));
File extFile = new File (Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDocuments), file.Name);
File extDir = extFile.ParentFile;
// Copy file to external storage to allow other apps to access ist
if (System.IO.File.Exists(extFile.AbsolutePath))
System.IO.File.Delete(extFile.AbsolutePath);
System.IO.File.Copy(file.AbsolutePath, extFile.AbsolutePath);
file.AbsolutePath, extFile.AbsolutePath);
// if copying was successful, start Intent for opening this file
if (System.IO.File.Exists(extFile.AbsolutePath))
{
Intent intent = new Intent();
intent.SetAction(Android.Content.Intent.ActionView);
intent.SetDataAndType(Android.Net.Uri.FromFile(extFile), mime);
MainApplication.FormsContext.StartActivityForResult(intent, 10);
}
}
catch (ActivityNotFoundException anfe)
{
// android could not find a suitable app for this file
var alert = new AlertDialog.Builder(MainApplication.FormsContext);
alert.SetTitle("Error");
alert.SetMessage("No suitable app found to open this file");
alert.SetCancelable(false);
alert.SetPositiveButton("Okay", (object sender, DialogClickEventArgs e) => ((AlertDialog)sender).Hide());
alert.Show();
}
catch (Exception ex)
{
// another exception
var alert = new AlertDialog.Builder(MainApplication.FormsContext);
alert.SetTitle("Error");
alert.SetMessage("Error when opening document");
alert.SetCancelable(false);
alert.SetPositiveButton("Okay", (object sender, DialogClickEventArgs e) => ((AlertDialog)sender).Hide());
alert.Show();
}
}
}
}
Please note that MainApplication.FormsContext is a static variable I added to my MainApplication.cs in order to be able to access the Context of the app quickly.
In your Android manifest, add
In your application resources, add an xml resource (into folder "xml") called file_paths.xml with the following content:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path name="root" path="/"/>
<external-files-path name="files" path="files" />
</paths>
Also you need to ensure that there are apps installed on the target device, which are able to handle the file in question. (Acrobat Reader, Word, Excel, etc...).
iOS
iOS already comes with a quite nice document preview built in, so you can simply use that (again create a file named "DocumentView.cs" in your iOS Project):
[assembly: Dependency(typeof(DocumentView))]
namespace MyApp.iOS.Services
{
public class DocumentView: IDocumentView
{
void IDocumentView.DocumentView(string file, string title)
{
UIApplication.SharedApplication.InvokeOnMainThread(() =>
{
QLPreviewController previewController = new QLPreviewController();
if (File.Exists(file))
{
previewController.DataSource = new PDFPreviewControllerDataSource(NSUrl.FromFilename(file), title);
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(previewController, true, null);
}
});
}
}
public class PDFItem : QLPreviewItem
{
public PDFItem(string title, NSUrl uri)
{
this.Title = title;
this.Url = uri;
}
public string Title { get; set; }
public NSUrl Url { get; set; }
public override NSUrl ItemUrl { get { return Url; } }
public override string ItemTitle { get { return Title; } }
}
public class PDFPreviewControllerDataSource : QLPreviewControllerDataSource
{
PDFItem[] sources;
public PDFPreviewControllerDataSource(NSUrl url, string filename)
{
sources = new PDFItem[1];
sources[0] = new PDFItem(filename, url);
}
public override IQLPreviewItem GetPreviewItem(QLPreviewController controller, nint index)
{
int idx = int.Parse(index.ToString());
if (idx < sources.Length)
return sources.ElementAt(idx);
return null;
}
public override nint PreviewItemCount(QLPreviewController controller)
{
return (nint)sources.Length;
}
}
}
Finally you can call
DependencyService.Get<IDocumentView>().DocumentView(file.path, "Title of the view");
to display the file in question.