简体   繁体   English

使用默认应用程序的Xamarin Android Open文件在Android 7或更高版本中不起作用

[英]Xamarin Android Open file using default app not work in Android 7 or above

I need to open documents or images using default app in android phone. 我需要使用Android手机中的默认应用打开文档或图像。 so I implemented following codes and it works good but not work only on Android 7 or above. 因此我实现了以下代码,效果很好,但不适用于Android 7或更高版本。 Please let me know what is wrong and how to fix. 请让我知道问题出在哪里以及如何解决。

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

var bytes = File.ReadAllBytes(filePath);

//Copy the private file's 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);

Originally I wasn't corresponding the android version for this functionality but after I read some questions like this , I added it. 本来我是不对应此功能的Android版本,但之后我读到这样一些问题这样 ,我加入吧。

Here is my manifest 这是我的清单

<?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 the app, it shows an exception in 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 这是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 may be related to the FileProvider that I declare in manifest. 我认为它可能与我在清单中声明的​​FileProvider有关。

Thanks for your help! 谢谢你的帮助!

I got the answer from @CommonsWare after having some discussion. 经过一番讨论,我从@CommonsWare得到了答案。

It needs to add one line to file_path.xml 它需要在file_path.xml中添加一行

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

here is full xml. 这是完整的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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM