Reputation: 3370
i'm triying to open a local pdf file in xamarin forms, my code:
var context = Forms.Context;
Java.IO.File javaFile = new Java.IO.File(filePath);
Android.Net.Uri uri = FileProvider.GetUriForFile(context, "myAuth.fileprovider", javaFile);
context.GrantUriPermission(context.PackageName, uri, ActivityFlags.GrantReadUriPermission);
Intent intent = new Intent(Intent.ActionView);
intent.SetDataAndType(uri, "application/pdf");
intent.SetFlags(ActivityFlags.ClearWhenTaskReset | ActivityFlags.NewTask);
Xamarin.Forms.Forms.Context.StartActivity(intent);
i followed several tutorials like this: How to get actual path from Uri xamarin android
But now my problem is that i don't know if the uri is getting the real path for the file:
i got this :
javaFile = "/storage/emulated/0/Download/myReport.pdf" (checked and exist)
uri = "content://myAuth.fileprovider/external_files/Download/myReport.pdf"
But i got this error on my pdf app "this file cannot be accessed". What i need to change to take the real path of the file? i think the problem is here:
Android.Net.Uri uri = FileProvider.GetUriForFile(context, "myAuth.fileprovider", javaFile);
But don't know what more change in order to work. Thx a lot!
Upvotes: 0
Views: 1606
Reputation: 3370
If someone has follow the steps before and still does not works, and the problem continues in the line var uri = FileProvider.GetUriForFile(context, context.ApplicationContext.PackageName + ".fileprovider", file);
. Check this too:
1 - Check if it's into Application tag
2 - Check the autority, usually you will use "${applicationId}.provider", but if not works, use a literal, for example myAuth.fileprovider
<application>
...
<provider ..android:authorities="myAuth.fileprovider" ..>
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"></meta-data>
</provider>
</application>
3 - Check the context, var context = Android.App.Application.Context;
it's the usually, but if this one does not works, you can try MainActivity.Current
, but you need to create first a static var into the MainActivity Class, something like this: public static MainActivity Current = null;
and initialize into the OnCreate Method Current = this;
. That's was my problem
4 - Check the type of the MimeType of the data, intent.SetDataAndType(uri, "application/pdf");
Thanks again to Leon Lu - MSFT for the answer, this is just an extension for anyone facing the same problem as me.
Upvotes: 0
Reputation: 9274
You should set the FileProvider in the application
tag of AndroidManifest.xml
.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.boxviewcolordemo" android:installLocation="auto">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
<application android:label="BoxViewColorDemo.Android">
<provider android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.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>
<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" />
</manifest>
Then create file_paths.xml
in the xml folder.
file_paths.xml
add following code.
<?xml version="1.0" encoding="utf-8" ?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="external"
path="." />
<external-files-path
name="external_files"
path="." />
<cache-path
name="cache"
path="." />
<external-cache-path
name="external_cache"
path="." />
<files-path
name="files"
path="." />
</paths>
Then in your dependenceService achievement, you should use following code. Note: FileProvider.GetUriForFile(context, context.ApplicationContext.PackageName + ".fileprovider", file);
the second attribute is you package name and ".fileprovider"
[assembly: Dependency(typeof(OpenPDF))]
namespace BoxViewColorDemo.Droid
{
public class OpenPDF : IOpenFile
{
public void OpenPDf(string filePath)
{
var rs = System.IO.File.Exists(filePath);
if (rs)
{
var context = Android.App.Application.Context;
var file = new Java.IO.File(filePath);
var uri = FileProvider.GetUriForFile(context, context.ApplicationContext.PackageName + ".fileprovider", file);
try
{
var intent = new Intent(Intent.ActionView);
intent.AddCategory(Intent.CategoryDefault);
intent.AddFlags(ActivityFlags.GrantReadUriPermission);
intent.AddFlags(ActivityFlags.ClearWhenTaskReset | ActivityFlags.NewTask);
intent.SetDataAndType(uri, "application/pdf");
context.StartActivity(intent);
}
catch (Exception e)
{
Toast.MakeText(context, e.Message, ToastLength.Long).Show();
}
}
}
}
}
And do not forget to grand the read/write permission at the runtime. For testing, you can add following code to the OnCreate
method of MainActivity.cs
.
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.WriteExternalStorage) != (int)Permission.Granted)
{
RequestPermissions(new string[] { Manifest.Permission.ReadExternalStorage, Manifest.Permission.WriteExternalStorage }, 0);
}
I put the pdf file to the Download folder, my filePath is DependencyService.Get<IOpenFile>().OpenPDf("/storage/emulated/0/Download/test.pdf");
Upvotes: 1