无法在Xamarin.Forms中读取Android的外部存储。

huangapple go评论62阅读模式
英文:

Unable to read external storage in Xamarin.Forms for Android

问题

在我们正在开发的Xamarin.Forms应用程序中,名为"myApp",仅针对Android设备,我们需要能够从文本文件中读取(可能还要写入):

storage/emulated/0/Android/data/com.myApp.configuration/myAppStuff.txt

在Windows 10开发平台中,该路径显示为:

This PC\DEVICE TYPE\Internal shared storage\Android\data\com.myApp.configuration\

在项目的AndroidManifest.xml文件中,我们已经包含了以下内容:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" ... >
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" tools:remove="android:maxSdkVersion"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:remove="android:maxSdkVersion"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:remove="android:maxSdkVersion"/>
</manifest>

在Visual Studio 2022中,可以通过以下步骤确认:

Project > myApp.Android Properties > Android Manifest > Required permissions:

观察所需的权限已被确认。

当应用程序在调试模式下首次启动时,在MainActivity.cs中:

AndroidX.Core.App.ActivityCompat.CheckSelfPermission(this, Android.Manifest.Permission.ReadExternalStorage)

返回"false",因此我们调用:

AndroidX.Core.App.ActivityCompat.RequestPermissions(this, new string[] { Android.Manifest.Permission.ReadExternalStorage, Android.Manifest.Permission.WriteExternalStorage, Android.Manifest.Permission.ManageExternalStorage }, 0)

Android显示一个(非模态)对话框,我们选择"ALLOW"。

稍后,以下代码:

File.Exists("/storage/emulated/0/Android/data/com.myApp.configuration/myAppStuff.txt")

返回"true",

但以下代码:

mystreamreader = new StreamReader("/storage/emulated/0/Android/data/com.myApp.configuration/myAppStuff.txt")

抛出异常,异常消息为:

"访问路径“/storage/emulated/0/Android/data/com.myApp.configuration/myAppStuff.txt”被拒绝。"

稍后的检查显示以下代码:

AndroidX.Core.App.ActivityCompat.CheckSelfPermission(this, Android.Manifest.Permission.ManageExternalStorage)

返回值为"false"。

为什么?

英文:

In the Xamarin.Forms application we are developing, called "myApp", targeting Android devices only, we need to be able to read from (and possibly write to) the text file

storage/emulated/0/Android/data/com.myApp.configuration/myAppStuff.txt

which in the Windows 10 development platform appears as

This PC\DEVICE TYPE\Internal shared storage\Android\data\com.myApp.configuration\

In the AndroidManifest.xml file for the project, we have included

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;manifest xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot; xmlns:tools=&quot;http://schemas.android.com/tools&quot; ... &gt;
&lt;uses-permission android:name=&quot;android.permission.READ_EXTERNAL_STORAGE&quot; tools:remove=&quot;android:maxSdkVersion&quot;/&gt;
&lt;uses-permission android:name=&quot;android.permission.WRITE_EXTERNAL_STORAGE&quot; tools:remove=&quot;android:maxSdkVersion&quot;/&gt;
&lt;uses-permission android:name=&quot;android.permission.MANAGE_EXTERNAL_STORAGE&quot; tools:remove=&quot;android:maxSdkVersion&quot;/&gt;
&lt;/manifest&gt;

This is confirmed in Visual Studio 2022 by navigating to

Project &gt; myApp.Android Properties &gt; Android Manifest &gt; Required permissions:

and observing the required permissions are asserted.

When the application is first started in the debug mode, in MainActivity.cs

AndroidX.Core.App.ActivityCompat.CheckSelfPermission(this, Android.Manifest.Permission.ReadExternalStorage)

returns "false", so we invoke

AndroidX.Core.App.ActivityCompat.RequestPermissions(this, new string[] { Android.Manifest.Permission.ReadExternalStorage, Android.Manifest.Permission.WriteExternalStorage, Android.Manifest.Permission.ManageExternalStorage }, 0)

Android shows a (non-modal) dialog

无法在Xamarin.Forms中读取Android的外部存储。

for which we select "ALLOW".

Later, the code

File.Exists(&quot;/storage/emulated/0/Android/data/com.myApp.configuration/myAppStuff.txt&quot;)

returns "true"

but the code

mystreamreader = new StreamReader(&quot;/storage/emulated/0/Android/data/com.myApp.configuration/myAppStuff.txt&quot;);

throws the exception with Message value of

&quot;Access to the path \&quot;/storage/emulated/0/Android/data/com.myApp.configuration/myAppStuff.txt\&quot; is denied.&quot;

A later check shows that the code

AndroidX.Core.App.ActivityCompat.CheckSelfPermission(this, Android.Manifest.Permission.ManageExternalStorage)

returns the value "false".

Why?

答案1

得分: 1

我无法重现你的问题。但你说:

我们需要能够从文本文件中读取(可能还要写入)内容

所以我创建了一个示例来读取和写入文本文件:

在我的 AndroidManifest.xml 中:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0"
        package="com.companyname.app21">
    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33" />
    <application android:label="App21.Android" android:theme="@style/MainTheme"></application>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>

请确保你的 AndroidManifest.xml 文件中的包名是 com.myApp.configuration

关于创建、读取和写入文件的代码如下:

FileStream filestream = new FileStream("/storage/emulated/0/Android/data/com.companyname.app21/test.txt",
                                     FileMode.OpenOrCreate,
                                     FileAccess.ReadWrite,
                                     FileShare.ReadWrite);
// 创建文本文件
File.WriteAllText("/storage/emulated/0/Android/data/com.companyname.app21/test.txt", "这是内容");
// 写入文本文件
var content = File.ReadAllText("/storage/emulated/0/Android/data/com.companyname.app21/test.txt);
// 读取文本文件

请注意,你需要根据你的实际需求替换文件路径和包名。

英文:

I can't reproduce your problem. But you said:

> we need to be able to read from (and possibly write to) the text file

So I created a sample to read and write the text file:

In my AndroidManifest.xml:

&lt;manifest xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot; android:versionCode=&quot;1&quot; android:versionName=&quot;1.0&quot;
              package=&quot;com.companyname.app21&quot;&gt;
    &lt;uses-sdk android:minSdkVersion=&quot;21&quot; android:targetSdkVersion=&quot;33&quot; /&gt;
    &lt;application android:label=&quot;App21.Android&quot; android:theme=&quot;@style/MainTheme&quot;&gt;&lt;/application&gt;
    &lt;uses-permission android:name=&quot;android.permission.ACCESS_NETWORK_STATE&quot; /&gt;
&lt;/manifest&gt;

Please make sure the package's value in your AndroidManifest.xml file is com.myApp.configuration.

And the code about create, read and write the file:

FileStream filestream = new FileStream(&quot;/storage/emulated/0/Android/data/com.companyname.app21/test.txt&quot;,
                                                     FileMode.OpenOrCreate,
                                                     FileAccess.ReadWrite,
                                                     FileShare.ReadWrite); 
// create the text file     
File.WriteAllText(&quot;/storage/emulated/0/Android/data/com.companyname.app21/test.txt&quot;, &quot;this is content&quot;);
// write the text file
var content = File.ReadAllText(&quot;/storage/emulated/0/Android/data/com.companyname.app21/test.txt&quot;);
//read the text file

答案2

得分: 0

自Android 13开始,EXTERNAL_STORAGE基本上已经不再存在。对它的CheckSelfPermission将自动返回false,就好像你之前回答“不再询问”一样。他们希望你转向使用不同的API,例如使用文档选择器来获取任意文件,或者成为文档提供程序来提供文件。

英文:

Which Android version? As of Android13, EXTERNAL_STORAGE is basically gone. CheckSelfPermission for it will auto-answer false, just as if you answered "No and do not ask again" before. They want you to move to different APIs, e.g. ask a Document Picker to get arbitrary files or be a Document Provider to provide them.

huangapple
  • 本文由 发表于 2023年2月7日 03:53:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/75365952.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定