Xamarin:Android:System.UnauthorizedAccessException:拒绝访问路径
Xamarin : Android : System.UnauthorizedAccessException: Access to the path is denied
所以我正在尝试创建一个文件,我得到了
System.UnauthorizedAccessException: 拒绝访问路径“/DownloadJitters”。我不确定这是不是权限问题(我已经尝试写入外部存储以防万一,但那没有用)还是其他原因。此外,我正在尝试找出一个写这些文件的好地方,因为我希望它们不容易被发现。有任何想法吗?这也是代码:
public void favouriteList(MainActivity av, Ordering o, string favouriteName, string totalCost, JittersListView jlv)
{
//Checks Directory exists
if (File.Exists(Android.OS.Environment.DirectoryDownloads + "/Jitters/FavouritesListAdded.txt") == false)
{
Directory.CreateDirectory(Android.OS.Environment.DirectoryDownloads + "Jitters/FavouriteList/");
File.Create(Android.OS.Environment.DirectoryDownloads + "/Jitters/FavouritesListAdded.txt");
}
if (File.Exists(Android.OS.Environment.DirectoryDownloads + "Jitters/FavouriteList/" + favouriteName + ".txt") == false)
{
var fav = File.Create(Android.OS.Environment.DirectoryDownloads + "Jitters/FavouriteList/" + favouriteName + ".txt");
fav.Close();
string file = Android.OS.Environment.DirectoryDownloads + "Jitters/FavouriteList/" + favouriteName + ".txt";
string added = null;
int current = 0;
while (true)
{
if (current < jlv.Count)
{
JittersListItem jli = jlv[current];
added += jli.Top + "|" + jli.Bottom + "|" + jli.itemPic + "|" + jli.itemDes + System.Environment.NewLine;
current++;
}
else
{
break;
}
}
File.AppendAllText(file, favouriteName + "|" + totalCost + added);
}
else
{
new AlertDialog.Builder(av)
.SetMessage("Please use a different name, this one has been taken.")
.Show();
}
}
这看起来像是复制粘贴错误 - 您应该学习将通用代码和表达式重构为一个值并重新使用它。
//Checks Directory exists
if (File.Exists(Android.OS.Environment.DirectoryDownloads + "/Jitters/FavouritesListAdded.txt") == false)
{
Directory.CreateDirectory(Android.OS.Environment.DirectoryDownloads + "Jitters/FavouriteList/");
File.Create(Android.OS.Environment.DirectoryDownloads + "/Jitters/FavouritesListAdded.txt");
}
我们假设 Android.OS.Environment.DirectoryDownloads
的值为 /Downloads
。现在逐行检查代码(你真的应该用调试器来做):
File.Exists(Android.OS.Environment.DirectoryDownloads + "/Jitters/FavouritesListAdded.txt")
这里的参数值会是"/Downloads/Jitters/FavouritesListAdded.txt"
- OK
Directory.CreateDirectory(Android.OS.Environment.DirectoryDownloads + "Jitters/FavouriteList/");
这里的文字字符串没有前导斜线,所以值将是:/DownloadsJitters/FavouriteList
- 我猜你可能是想 /Downloads/Jitters/FavouriteList
.
与其确保将斜线添加到代码中的所有 6 个路径表达式,不如创建一个具有路径值 的变量并重复使用它。
好的我通过将保存位置更改为来修复它
System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal)
当他们需要相同的权限时,不要问我为什么这样做有效。
首先将此权限添加到您的清单中:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
从 Android 6.0 (API 23) 开始,您还需要手动请求权限,将此代码添加到 Xamarin.Android 项目的 MainActivity.cs 中:
if ((ContextCompat.CheckSelfPermission(this, Manifest.Permission.WriteExternalStorage) != (int)Permission.Granted)
|| (ContextCompat.CheckSelfPermission(this, Manifest.Permission.ReadExternalStorage) != (int)Permission.Granted))
{
ActivityCompat.RequestPermissions(this, new string[] { Manifest.Permission.ReadExternalStorage, Manifest.Permission.WriteExternalStorage }, REQUEST);
}
从 Android 10 开始,您可能还需要像这样向清单添加 android:requestLegacyExternalStorage
属性:
<application android:requestLegacyExternalStorage="true" />
更新
完成所有这些后,您可能仍然会在 Android 11 或更高版本上遇到异常如果您尝试在 SD 卡的任何路径上保存文件,则只能使用您的外部存储和内部存储路径默认应用。
您应用程序的私有外部存储路径:
Android.App.Application.Context.GetExternalFilesDir(null).AbsolutePath
您应用程序的私有内部存储路径:
System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData)
如果您需要访问Android 11或更高版本的SDCARD的任何路径,您应该请求管理所有文件访问权限。
private void RequestStorageAccess()
{
if (!Environment.IsExternalStorageManager)
{
StartActivityForResult(new Intent(Android.Provider.Settings.ActionManageAllFilesAccessPermission), 3);
}
}
这将弹出一个 Activity 列出所有有权访问所有文件访问权限的应用程序,用户应点击您的应用程序并启用权限。
但是为了让您的应用出现在那里,您应该将此权限添加到您的清单中:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
并且您还需要确保使用 Android 11 或更高版本编译您的应用程序。
这里可以看到权限Activity:
出于某种原因,我可以在没有此权限的情况下将文件保存到文档文件夹,但是删除文件后我无法再次创建具有相同名称的相同文件,而且我无法列出所有文件,这就是为什么即使使用文档目录也需要此弹出窗口的原因。
仅在您确实需要时使用管理所有文件权限
如果您想在 Google Play 中使用“管理所有文件权限”发布您的应用程序,您必须在 Google Play 中填写“权限声明表”,因为它是被认为是
“高危或敏感权限”这里有更多信息,Google应该批准:
https://support.google.com/googleplay/android-developer/answer/9214102?hl=en#zippy=
何时请求此权限:
https://support.google.com/googleplay/android-developer/answer/10467955?hl=en
如果您在 Xamarin 中写入或读取文件时仍然收到 UnauthorizedAccessException Android。我刚刚写了一篇文章来解决它
http://bsubramanyamraju.blogspot.com/2019/12/resolved-unauthorizedaccessexception.html
Xamarin.Forms(Android解)
MainActivity.cs
- For apps that target Android 5.1(API level 22) or lower, there is nothing more that needs to be done.
- Apps that will run on Android 6.0(API 23 level 23) or higher should ask Run time permission checks.
protected override void OnCreate(Bundle bundle)
{
if (Build.VERSION.SdkInt >= BuildVersionCodes.M)
{
if (!(CheckPermissionGranted(Manifest.Permission.ReadExternalStorage) && !CheckPermissionGranted(Manifest.Permission.WriteExternalStorage)))
{
RequestPermission();
}
}
LoadApplication(new App());
}
private void RequestPermission()
{
ActivityCompat.RequestPermissions(this, new string[] { Manifest.Permission.ReadExternalStorage, Manifest.Permission.WriteExternalStorage }, 0);
}
public bool CheckPermissionGranted(string Permissions)
{
// Check if the permission is already available.
if (ActivityCompat.CheckSelfPermission(this, Permissions) != Permission.Granted)
{
return false;
}
else
{
return true;
}
}
所以我正在尝试创建一个文件,我得到了 System.UnauthorizedAccessException: 拒绝访问路径“/DownloadJitters”。我不确定这是不是权限问题(我已经尝试写入外部存储以防万一,但那没有用)还是其他原因。此外,我正在尝试找出一个写这些文件的好地方,因为我希望它们不容易被发现。有任何想法吗?这也是代码:
public void favouriteList(MainActivity av, Ordering o, string favouriteName, string totalCost, JittersListView jlv)
{
//Checks Directory exists
if (File.Exists(Android.OS.Environment.DirectoryDownloads + "/Jitters/FavouritesListAdded.txt") == false)
{
Directory.CreateDirectory(Android.OS.Environment.DirectoryDownloads + "Jitters/FavouriteList/");
File.Create(Android.OS.Environment.DirectoryDownloads + "/Jitters/FavouritesListAdded.txt");
}
if (File.Exists(Android.OS.Environment.DirectoryDownloads + "Jitters/FavouriteList/" + favouriteName + ".txt") == false)
{
var fav = File.Create(Android.OS.Environment.DirectoryDownloads + "Jitters/FavouriteList/" + favouriteName + ".txt");
fav.Close();
string file = Android.OS.Environment.DirectoryDownloads + "Jitters/FavouriteList/" + favouriteName + ".txt";
string added = null;
int current = 0;
while (true)
{
if (current < jlv.Count)
{
JittersListItem jli = jlv[current];
added += jli.Top + "|" + jli.Bottom + "|" + jli.itemPic + "|" + jli.itemDes + System.Environment.NewLine;
current++;
}
else
{
break;
}
}
File.AppendAllText(file, favouriteName + "|" + totalCost + added);
}
else
{
new AlertDialog.Builder(av)
.SetMessage("Please use a different name, this one has been taken.")
.Show();
}
}
这看起来像是复制粘贴错误 - 您应该学习将通用代码和表达式重构为一个值并重新使用它。
//Checks Directory exists
if (File.Exists(Android.OS.Environment.DirectoryDownloads + "/Jitters/FavouritesListAdded.txt") == false)
{
Directory.CreateDirectory(Android.OS.Environment.DirectoryDownloads + "Jitters/FavouriteList/");
File.Create(Android.OS.Environment.DirectoryDownloads + "/Jitters/FavouritesListAdded.txt");
}
我们假设 Android.OS.Environment.DirectoryDownloads
的值为 /Downloads
。现在逐行检查代码(你真的应该用调试器来做):
File.Exists(Android.OS.Environment.DirectoryDownloads + "/Jitters/FavouritesListAdded.txt")
这里的参数值会是"/Downloads/Jitters/FavouritesListAdded.txt"
- OK
Directory.CreateDirectory(Android.OS.Environment.DirectoryDownloads + "Jitters/FavouriteList/");
这里的文字字符串没有前导斜线,所以值将是:/DownloadsJitters/FavouriteList
- 我猜你可能是想 /Downloads/Jitters/FavouriteList
.
与其确保将斜线添加到代码中的所有 6 个路径表达式,不如创建一个具有路径值 的变量并重复使用它。
好的我通过将保存位置更改为来修复它 System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal)
当他们需要相同的权限时,不要问我为什么这样做有效。
首先将此权限添加到您的清单中:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
从 Android 6.0 (API 23) 开始,您还需要手动请求权限,将此代码添加到 Xamarin.Android 项目的 MainActivity.cs 中:
if ((ContextCompat.CheckSelfPermission(this, Manifest.Permission.WriteExternalStorage) != (int)Permission.Granted)
|| (ContextCompat.CheckSelfPermission(this, Manifest.Permission.ReadExternalStorage) != (int)Permission.Granted))
{
ActivityCompat.RequestPermissions(this, new string[] { Manifest.Permission.ReadExternalStorage, Manifest.Permission.WriteExternalStorage }, REQUEST);
}
从 Android 10 开始,您可能还需要像这样向清单添加 android:requestLegacyExternalStorage
属性:
<application android:requestLegacyExternalStorage="true" />
更新
完成所有这些后,您可能仍然会在 Android 11 或更高版本上遇到异常如果您尝试在 SD 卡的任何路径上保存文件,则只能使用您的外部存储和内部存储路径默认应用。
您应用程序的私有外部存储路径:
Android.App.Application.Context.GetExternalFilesDir(null).AbsolutePath
您应用程序的私有内部存储路径:
System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData)
如果您需要访问Android 11或更高版本的SDCARD的任何路径,您应该请求管理所有文件访问权限。
private void RequestStorageAccess()
{
if (!Environment.IsExternalStorageManager)
{
StartActivityForResult(new Intent(Android.Provider.Settings.ActionManageAllFilesAccessPermission), 3);
}
}
这将弹出一个 Activity 列出所有有权访问所有文件访问权限的应用程序,用户应点击您的应用程序并启用权限。
但是为了让您的应用出现在那里,您应该将此权限添加到您的清单中:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
并且您还需要确保使用 Android 11 或更高版本编译您的应用程序。
这里可以看到权限Activity:
出于某种原因,我可以在没有此权限的情况下将文件保存到文档文件夹,但是删除文件后我无法再次创建具有相同名称的相同文件,而且我无法列出所有文件,这就是为什么即使使用文档目录也需要此弹出窗口的原因。
仅在您确实需要时使用管理所有文件权限
如果您想在 Google Play 中使用“管理所有文件权限”发布您的应用程序,您必须在 Google Play 中填写“权限声明表”,因为它是被认为是 “高危或敏感权限”这里有更多信息,Google应该批准:
https://support.google.com/googleplay/android-developer/answer/9214102?hl=en#zippy=
何时请求此权限:
https://support.google.com/googleplay/android-developer/answer/10467955?hl=en
如果您在 Xamarin 中写入或读取文件时仍然收到 UnauthorizedAccessException Android。我刚刚写了一篇文章来解决它 http://bsubramanyamraju.blogspot.com/2019/12/resolved-unauthorizedaccessexception.html
Xamarin.Forms(Android解)
MainActivity.cs
- For apps that target Android 5.1(API level 22) or lower, there is nothing more that needs to be done.
- Apps that will run on Android 6.0(API 23 level 23) or higher should ask Run time permission checks.
protected override void OnCreate(Bundle bundle)
{
if (Build.VERSION.SdkInt >= BuildVersionCodes.M)
{
if (!(CheckPermissionGranted(Manifest.Permission.ReadExternalStorage) && !CheckPermissionGranted(Manifest.Permission.WriteExternalStorage)))
{
RequestPermission();
}
}
LoadApplication(new App());
}
private void RequestPermission()
{
ActivityCompat.RequestPermissions(this, new string[] { Manifest.Permission.ReadExternalStorage, Manifest.Permission.WriteExternalStorage }, 0);
}
public bool CheckPermissionGranted(string Permissions)
{
// Check if the permission is already available.
if (ActivityCompat.CheckSelfPermission(this, Permissions) != Permission.Granted)
{
return false;
}
else
{
return true;
}
}