Xamarin Android Open file using default app not working in Android 7 or higher

I need to open documents or images using the default app in an android phone. so I have implemented the following codes and it works well but does not work only on Android 7 or higher. Please let me know what is wrong and how to fix it.

var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
var filePath = Path.Combine(documentsPath, fileName);

var bytes = File.ReadAllBytes(filePath);

//Copy the private file data to the EXTERNAL PUBLIC location
string externalStorageState = global::Android.OS.Environment.ExternalStorageState;
var externalPath = global::Android.OS.Environment.ExternalStorageDirectory.Path + "/" + global::Android.OS.Environment.DirectoryDownloads + "/" + fileName;
File.WriteAllBytes(externalPath, bytes);

Java.IO.File file = new Java.IO.File(externalPath);
file.SetReadable(true);

string application = "";
string extension = Path.GetExtension(filePath);

// get mimeTye
switch (extension.ToLower())
{
    case ".txt":
    application = "text/plain";
    break;
    case ".doc":
    case ".docx":
    application = "application/msword";
    break;
    case ".pdf":
    application = "application/pdf";
    break;
    case ".xls":
    case ".xlsx":
    application = "application/vnd.ms-excel";
    break;
    case ".jpg":
    case ".jpeg":
    case ".png":
    application = "image/jpeg";
    break;
    default:
    application = "*/*";
    break;
}

Intent intent = new Intent(Intent.ActionView);
Android.Net.Uri uri = Android.Net.Uri.FromFile(file);
Context context = MainActivity.instance;

if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.N)
{
    uri = FileProvider.GetUriForFile(context, context.PackageName + ".fileprovider", file);
    intent.SetDataAndType(uri, application);
    intent.SetFlags(ActivityFlags.GrantReadUriPermission);
    intent.AddFlags(ActivityFlags.NoHistory);
}
else
{
    intent.SetDataAndType(uri, application);
    intent.SetFlags(ActivityFlags.ClearWhenTaskReset | ActivityFlags.NewTask);
}

context.StartActivity(intent);

      

Initially I didn't match the Android version for this feature, but after reading some questions like I added it.

Here is my manifesto

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1" package="com.ibase.mtwpublicapp">
    <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="26" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <application android:label="OKS" android:largeHeap="true">
        <provider android:name="android.support.v4.content.FileProvider" android:authorities="com.oks.mobileapp.fileprovider" android:exported="false" android:grantUriPermissions="true">
            <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"></meta-data>
        </provider>
        <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id" />
    </application>
</manifest>

      

When I test my application, an exception is displayed on this line.

uri = FileProvider.GetUriForFile(context, context.PackageName + ".fileprovider", file);

      

here is the exception message.

 {Java.Lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Download/237309880.doc
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <657aa8fea4454dc898a9e5f379c58734>:0 
  at Java.Interop.JniEnvironment+StaticMethods.CallStaticObjectMethod (Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x00069] in <54816278eed9488eb28d3597fecd78f8>:0 
  at Android.Runtime.JNIEnv.CallStaticObjectMethod (System.IntPtr jclass, System.IntPtr jmethod, Android.Runtime.JValue* parms) [0x00000] in /Users/builder/data/lanes/5749/d8c6e504/source/xamarin-android/src/Mono.Android/Android.Runtime/JNIEnv.g.cs:562 
  at Android.Support.V4.Content.FileProvider.GetUriForFile (Android.Content.Context context, System.String authority, Java.IO.File file) [0x00077] in <e43264129f744fc09346a273ec4f6c48>:0 
  at FileManagement.Helpers.FileHelper.OpenFileByName (System.String fileName) [0x0022a] in FileManagement/Helpers/FileHelper.cs:141 
  --- End of managed Java.Lang.IllegalArgumentException stack trace ---
java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Download/237309880.doc
    at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:712)
    at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:401)
    at android.support.v7.app.AlertDialog_IDialogInterfaceOnClickListenerImplementor.n_onClick(Native Method)
    at android.support.v7.app.AlertDialog_IDialogInterfaceOnClickListenerImplementor.onClick(AlertDialog_IDialogInterfaceOnClickListenerImplementor.java:30)
    at android.support.v7.app.AlertController$ButtonHandler.handleMessage(AlertController.java:162)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6776)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1518)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1408)
}

      

Here is the file_paths.xml

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

      

I think it might have something to do with the FileProvider that I declare in the manifest.

Thank you for your help!

0


source to share


1 answer


I got a response from @CommonsWare after discussion.

It should add one line to file_path.xml

<external-path name="my_downloads" path="Download" />

      



here's the complete xml.

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="my_downloads" path="Download" />
    <external-files-path name="my_images" path="Pictures" />
    <external-files-path name="my_movies" path="Movies" />
</paths>

      

0


source







All Articles