Я новичок (как на двух курсах Udemy C# и паре видеороликов с кодом игры ti c ta c toe & snake на YouTube для начинающих, поэтому, пожалуйста, извините за мое незнание) с помощью Visual Studio 19 и Xamarin для Android, чтобы создать приложение-парсер для моего телефона Android. Основная проблема, с которой я столкнулся, заключается в том, что когда я использую метод WebClient
DownloadFile
, я получаю «System. Net .WebException» (System.UnauthorizedAccessException) со словами «Доступ к пути [имя файла] запрещен».
Я нашел несколько других сообщений в стеке с похожими проблемами, и все они сказали, что проблема не в проверке / предоставлении разрешений, но даже после добавления кода для запроса / предоставления разрешения я получу такое же исключение. Возможно, я добавил код неправильно, но я так не думал, поскольку, когда я тестировал его на эмуляторе, всплывающее окно с разрешениями, казалось, работало. Вот исключение:
"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 документация для разработчиков , но в конце концов решил оставить как есть.
Любая помощь будет принята с благодарностью, и я постараюсь ответить на любые вопросы, которые могу. Я просмотрел много документации, но иногда мне кажется, что лучше обратиться за помощью к кому-нибудь более опытному, чем я.