即使在获得应用程序权限后,"DownloadFile"也无法在Android(版本10)中运行的问题



我是一个初学者(就像在YouTube初学者上的两门Udemy C#课程和几个井字游戏和蛇游戏代码视频中一样,所以请原谅我的无知(,我使用Visual Studio 19和Xamarin for Android为我的安卓手机创建了一个网页抓取应用程序。我一直面临的主要问题是,当我使用WebClientDownloadFile方法时;System.Net.WebException";(System.UnauthorizedAccessException(说";拒绝访问路径[filename]">

我发现其他一些堆栈帖子也有类似的问题,他们都说问题不是检查/授予权限,但即使添加了请求/授予权限的代码,我也会得到同样的异常。我可能添加了错误的代码,但我不这么认为,因为当我在模拟器上测试它时,权限弹出窗口似乎可以工作。例外情况如下:

"Access to the path "/storage/emulated/0/Download/6855288302363331845.mp4" is denied."

这是我从URI下载视频的代码:

public static void DownloadVideo(string htmlCode)
{
string fullID = GetVideoID(htmlCode);
string fullLink = GetVideoLink(htmlCode);
//android filepath (or is it?)
string directory = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Android.OS.Environment.DirectoryDownloads);
string file = Path.Combine(directory, fullID + ".mp4");
//download video
using (WebClient downloadClient = new WebClient())
{
downloadClient.DownloadFile(fullLink, file);
}
}

我总是在downloadClient.DownloadFile(fullLink, file);行得到异常。

我也尝试过使用MediaStore,但老实说,我真的不明白它和上下文是如何工作的。

以下是我添加到AndroidManifest.xml:的权限

<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<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" />

这是OnCreate代码:

protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);

//get ui controls
EditText videoUrl = FindViewById<EditText>(Resource.Id.urlInput);
Button processButton = FindViewById<Button>(Resource.Id.button1);
Button dlButton = FindViewById<Button>(Resource.Id.button3);
Button rsButton = FindViewById<Button>(Resource.Id.button2);
Button permissions = FindViewById<Button>(Resource.Id.button4);
TextView confirmation = FindViewById<TextView>(Resource.Id.textConfirmation);
EditText videoID = FindViewById<EditText>(Resource.Id.editText1);
EditText videoLink = FindViewById<EditText>(Resource.Id.editText2);

//process
processButton.Click += (sender, e) =>
{
string startingUrl = videoUrl.Text.ToString();
string htmlCode = "";
if (startingUrl.Contains("tiktok") != true)
{
Core.UrlDownloadAction.UpdateLabel(confirmation, "Invalid Link");
}
else
{
htmlCode = Core.UrlDownloadAction.DownloadHTML(startingUrl);
videoID.Text = Core.UrlDownloadAction.GetVideoID(htmlCode);
videoLink.Text = Core.UrlDownloadAction.GetVideoLink(htmlCode);
confirmation.Text = "Successfully Processed";

}

};
//download
dlButton.Click += (sender, e) =>
{
string startingUrl = videoUrl.Text.ToString();
string fullVideoID = videoID.Text.ToString();
string htmlCode = Core.UrlDownloadAction.DownloadHTML(startingUrl);


//download video
if (startingUrl.Contains("tiktok") != true)
{
Core.UrlDownloadAction.UpdateLabel(confirmation, "Invalid Link");
}
else
{
//check & request permissions
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.WriteExternalStorage) != (int)Permission.Granted)
{
RequestPermissions(new string[] { Manifest.Permission.WriteExternalStorage }, 257);
}
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.ReadExternalStorage) != (int)Permission.Granted)
{
RequestPermissions(new string[] { Manifest.Permission.ReadExternalStorage }, 256);
}
//download
if (htmlCode == "failed")
{
confirmation.Text = "Invalid HTML";
}
else
{
Core.UrlDownloadAction.DownloadVideo(htmlCode);
confirmation.Text = "Successful Download";
}
}
/*if (!(ContextCompat.CheckSelfPermission(this, Manifest.Permission.ReadExternalStorage) == Permission.Granted)*//* && !(ContextCompat.CheckSelfPermission(this, Manifest.Permission.WriteExternalStorage) == Permission.Granted)*//*)
{
if ((ShouldShowRequestPermissionRationale(Manifest.Permission.ReadExternalStorage)))*//* && (ShouldShowRequestPermissionRationale(Manifest.Permission.WriteExternalStorage)))*//*
{
Toast.MakeText(this, "Storage permissions are needed to save the file.", ToastLength.Short).Show();
}
//reqest read/write permissions
RequestPermissions(new string[] { Manifest.Permission.ReadExternalStorage }, requestCode: 256);
RequestPermissions(new string[] { Manifest.Permission.WriteExternalStorage }, requestCode: 257);
}
else
{

}*/
};

rsButton.Click += (sender, e) =>
{
Core.UrlDownloadAction.ResetDownloader(videoUrl, confirmation, videoID, videoLink);
};
}

我曾经用不同的方式实现检查权限代码(如注释代码中所示(,最初在Android开发人员文档的视频教程中显示了它,但最终决定保持原样。

任何帮助都将不胜感激,我会尽力回答任何问题。我查阅了很多文件,但有时我觉得最好找一个比我更有经验的人帮忙。

从Android 6.0开始,Android需要运行时权限。当您想要下载文件时,需要存储权限。

我制作了关于如何使用您提供的DownloadVideo方法从链接下载的代码示例。由于我没有视频链接,我使用图片下载链接作为参考。

public class Activity_layout1 : Activity
{
public string TAG
{
get
{
return "Activity1";
}
}
static readonly int REQUEST_STORAGES = 1;
static string[] PERMISSIONS_STORAGES = {
Manifest.Permission.ReadExternalStorage,
Manifest.Permission.WriteExternalStorage
};
View layout;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your application here
SetContentView(Resource.Layout.layout1);
var Request_Permission = FindViewById<Button>(Resource.Id.btn_RequestPermission);
Request_Permission.Click += delegate
{
Log.Info(TAG, "Show Storage button pressed. Checking permissions.");
// Verify that all required contact permissions have been granted.
if (ActivityCompat.CheckSelfPermission(this, Manifest.Permission.ReadExternalStorage) != (int)Permission.Granted
|| ActivityCompat.CheckSelfPermission(this, Manifest.Permission.WriteExternalStorage) != (int)Permission.Granted)
{
// Contacts permissions have not been granted.
Log.Info(TAG, "Storage permissions has NOT been granted. Requesting permissions.");
RequestContactsPermissions();
}
else
{
// Contact permissions have been granted. Show the contacts fragment.
Log.Info(TAG, "Storage permissions have already been granted.");
}
};
var Download = FindViewById<Button>(Resource.Id.btn_Download);
Download.Click += delegate
{
//android filepath (or is it?)
string directory = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Android.OS.Environment.DirectoryDownloads);
string file = Path.Combine(directory, "abc" + ".jpg");
//download video
using (WebClient downloadClient = new WebClient())
{
downloadClient.DownloadFile("http://www.dada-data.net/uploads/image/hausmann_abcd.jpg", file);
}
};
var Check = FindViewById<Button>(Resource.Id.btn_CheckFile);
Check.Click += delegate
{
string directory = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Android.OS.Environment.DirectoryDownloads);
string file = Path.Combine(directory, "abc" + ".jpg");
if (File.Exists(file))
{
Android.App.AlertDialog.Builder dialog = new AlertDialog.Builder(this);
AlertDialog alert = dialog.Create();
alert.SetTitle("File Check");
alert.SetMessage("File Exists!!!");
alert.SetButton("OK", (c, ev) =>
{
// Ok button click task  
});
alert.Show();
}
};
}
void RequestContactsPermissions()
{
if (ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.ReadContacts)
|| ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.WriteContacts))
{
Log.Info(TAG, "Displaying storage permission rationale to provide additional context.");
// Display a SnackBar with an explanation and a button to trigger the request.
Snackbar.Make(layout, "Storage Permission is needed",
Snackbar.LengthIndefinite).SetAction("OK", new Action<View>(delegate (View obj)
{
ActivityCompat.RequestPermissions(this, PERMISSIONS_STORAGES, REQUEST_STORAGES);
})).Show();
}
else
{
//  permissions have not been granted yet. Request them directly.
ActivityCompat.RequestPermissions(this, PERMISSIONS_STORAGES, REQUEST_STORAGES);
}
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
{
if (requestCode == REQUEST_STORAGES)
{
// Received permission result for  permission.
Log.Info(TAG, "Received response for Storage permission request.");
// Check if the only required permission has been granted
if ((grantResults.Length == 1) && (grantResults[0] == Permission.Granted))
{
Log.Info(TAG, "Storage permission has now been granted.");
}
else
{
Log.Info(TAG, "Storage permission was NOT granted.");
}
}
else
{
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}

在Android 10/Q上,使用的路径不可访问。这里已经报道了一百次了。

您仍然可以通过将legacyExternalStorage true添加到清单文件来获得访问权限。这个你也可以在stackoverflow上读一百遍。

相关内容

  • 没有找到相关文章

最新更新