英文:
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
<?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>
This is confirmed in Visual Studio 2022 by navigating to
Project > myApp.Android Properties > Android Manifest > 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
for which we select "ALLOW".
Later, the code
File.Exists("/storage/emulated/0/Android/data/com.myApp.configuration/myAppStuff.txt")
returns "true"
but the code
mystreamreader = new StreamReader("/storage/emulated/0/Android/data/com.myApp.configuration/myAppStuff.txt");
throws the exception with Message value of
"Access to the path \"/storage/emulated/0/Android/data/com.myApp.configuration/myAppStuff.txt\" is denied."
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:
<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>
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("/storage/emulated/0/Android/data/com.companyname.app21/test.txt",
FileMode.OpenOrCreate,
FileAccess.ReadWrite,
FileShare.ReadWrite);
// create the text file
File.WriteAllText("/storage/emulated/0/Android/data/com.companyname.app21/test.txt", "this is content");
// write the text file
var content = File.ReadAllText("/storage/emulated/0/Android/data/com.companyname.app21/test.txt");
//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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论