Перейти к содержанию
  • 0
Delpher-X

Не могу скачать файл в Android - permission denied

Вопросы

Здравствуйте. У меня такая проблема. 

Пытаюсь скачать файл:
 

var
S : TMemoryStream;
begin
S := TMemoryStream.Create();
IdHTTP1.Get('http://sitename.com/7UlmBU7IXHA.jpg', S);
S.SaveToFile('/storage/emulated/0/ImageFile.jpg');
S.Free;
end;


Проблема возникает на последней стадии - при сохранении файла. Android пишет, Cannot create file: '/storage/emulated/0/ImageFile.jpg'. Permission denied, то есть доступ запрещен. Но как его разрешить? Когда я устанавливаю приложение, система пишет, что никаких разрешений данная программа не требует.

Поделиться сообщением


Ссылка на сообщение

Рекомендуемые сообщения

  • 0
45 минут назад, Delpher-X сказал:

Здравствуйте. У меня такая проблема. 

Пытаюсь скачать файл:
 


var
S : TMemoryStream;
begin
S := TMemoryStream.Create();
IdHTTP1.Get('http://sitename.com/7UlmBU7IXHA.jpg', S);
S.SaveToFile('/storage/emulated/0/ImageFile.jpg');
S.Free;
end;


Проблема возникает на последней стадии - при сохранении файла. Android пишет, Cannot create file: '/storage/emulated/0/ImageFile.jpg'. Permission denied, то есть доступ запрещен. Но как его разрешить? Когда я устанавливаю приложение, система пишет, что никаких разрешений данная программа не требует.

Выдать разрешения в манифесте

Запросить при необходимости в рантайме из кода

И путь брать через System.IOUtils

Поделиться сообщением


Ссылка на сообщение
  • 0
1 час назад, mazayhin сказал:

Выдать разрешения в манифесте

А как сделать этот манифест? 

1 час назад, mazayhin сказал:

Запросить при необходимости в рантайме из кода

Аналогичный вопрос. 

1 час назад, mazayhin сказал:

И путь брать через System.IOUtils

Нельзя ли поподробнее? Что за System.IOUtils

Поделиться сообщением


Ссылка на сообщение
  • 0

Изучите особенности программирования под Android, общее устройство этой ОС, структуру apk файлов (сначала будет трудно, но иначе ничего у вас не получится).

Про манифест: https://developer.android.com/guide/topics/manifest/manifest-intro

Отвечу на ваши вопросы, но сейчас толку будет мало:

Файл-шаблон манифеста AndroidManifest.template.xml создается автоматически при создании проекта (копируется в папку проекта), окончательный файл манифеста формируется при сборке проекта, разрешения для работы с внешним хранилищем даны по-умолчанию (чтение+запись).

1361862021_.thumb.png.268444edc464a12e01fbf2193aa515b6.png

но перед работой с внешним хранилищем в программе необходимо явно запросить разрешение у пользователя (если пользователь уже дал разрешение, то диалога-запроса не будет, код выполнится сразу без запроса):

1239924948_.png.300db18f2b767483d3f95e6ddf985da7.png

System.IOUtils - кроссплатформенная библиотека для работы с файлами (папками и прочее)..  Пример вызова: TFile.WriteAllText().

Советую изучить ее исходный код.

 

 

Поделиться сообщением


Ссылка на сообщение
  • 0
В 23.01.2021 в 14:42, slav_z сказал:

Файл-шаблон манифеста AndroidManifest.template.xml создается автоматически при создании проекта (копируется в папку проекта), окончательный файл манифеста формируется при сборке проекта, разрешения для работы с внешним хранилищем даны по-умолчанию (чтение+запись).

Я посмотрел. У меня там стоит галочка True и в пункте Read eternal storage и в Write eternal storage. 

Кстати, если этот манифест нужно распространять вместе с приложением - то как? Все приложения которые я видел, распространялись исключительно как установочные APK-файлы, никаких XML-файлов к ним не прилагалось. Или, для Android тоже нужны программы для создания установочных файлов, как и для Windows? 

В 23.01.2021 в 14:42, slav_z сказал:

System.IOUtils - кроссплатформенная библиотека для работы с файлами (папками и прочее).. 

Где можно почитать про нее? 

 

Поделиться сообщением


Ссылка на сообщение
  • 0

И кстати, 

В 23.01.2021 в 14:42, slav_z сказал:

но перед работой с внешним хранилищем в программе необходимо явно запросить разрешение у пользователя (если пользователь уже дал разрешение, то диалога-запроса не будет, код выполнится сразу без запроса):

Код который изображен на картинке - нерабочий. В том смысле, что он вообще не компилируется. var и := в самом начале, подчеркиваются красным. 

Также подчеркивается красным запятая в выражении RequestPermissions([WriteStorage], 

и Granted в (AGrantResults[0] = TPermissionStatus.Granted) 

Поделиться сообщением


Ссылка на сообщение
  • 0
3 минуты назад, Delpher-X сказал:

И кстати, 

Код который изображен на картинке - нерабочий. В том смысле, что он вообще не компилируется. var и := в самом начале, подчеркиваются красным. 

Также подчеркивается красным запятая в выражении RequestPermissions([WriteStorage], 

и Granted в (AGrantResults[0] = TPermissionStatus.Granted) 

потому что у вас старая версия делфи. Уточните, какая именно?

Поделиться сообщением


Ссылка на сообщение
  • 0
2 минуты назад, Tumaso сказал:

потому что у вас старая версия делфи. Уточните, какая именно?

Delphi.Rio. 

Отредактировал Delpher-X

Поделиться сообщением


Ссылка на сообщение
  • 0
4 часа назад, Delpher-X сказал:

Код который изображен на картинке - нерабочий

объявите переменную WRITE_EXTERNAL_STORAGE обычным способом типа string. все остальные ошибки компиляции - следствие первой...

9 часов назад, Delpher-X сказал:

Кстати, если этот манифест нужно распространять вместе с приложением - то как?

при сборке он автоматически включается в APK-файл..  ничего делать для этого не нужно... APK-файл это обычный ZIP-файл... измените расширение на ZIP и откройте, посмотрите что у него внутри...

9 часов назад, Delpher-X сказал:

Где можно почитать про нее?

хотя бы здесь: http://www.proghouse.ru/programming/126-ioutils

Поделиться сообщением


Ссылка на сообщение
  • 0
1 минуту назад, slav_z сказал:

объявите переменную WRITE_EXTERNAL_STORAGE обычным способом типа string.

А, так это строковый тип. Так бы сразу и сказали, а то непонятно. 

2 минуты назад, slav_z сказал:

ри сборке он автоматически включается в APK-файл..  ничего делать для этого не нужно... APK-файл это обычный ZIP-файл... измените расширение на ZIP и откройте, посмотрите что у него внутри...

Только что посмотрел - и вправду есть. Но почему же тогда все же разрешения для приложения никак не отображаются при установке? 

4 минуты назад, slav_z сказал:

Спасибо, уже сам нашел. 

Поделиться сообщением


Ссылка на сообщение
  • 0
7 минут назад, slav_z сказал:

объявите переменную WRITE_EXTERNAL_STORAGE обычным способом типа string. все остальные ошибки компиляции - следствие первой...

Попробовал. В результате теперь там все полыхает красным подчеркиванием. 

Поделиться сообщением


Ссылка на сообщение
  • 0
41 минут назад, Delpher-X сказал:

Но почему же тогда все же разрешения для приложения никак не отображаются при установке? 

такое поведение было у старых андроидов...  теперь необходимо запрашивать разрешение у пользователя прям тогда, когда программе это реально нужно...

40 минут назад, Delpher-X сказал:

В результате теперь там все полыхает красным подчеркиванием. 

подключить модули в uses не забыли ? (см. картинку с кодом)

Поделиться сообщением


Ссылка на сообщение
  • 0
1 минуту назад, slav_z сказал:

подключить модули в uses не забыли ? (см. картинку с кодом)

Все подключил, в точности как на картинке. 

Поделиться сообщением


Ссылка на сообщение
  • 0
1 час назад, Delpher-X сказал:

Попробовал. В результате теперь там все полыхает красным подчеркиванием. 

 

22 минут назад, slav_z сказал:

подключить модули в uses не забыли ? (см. картинку с кодом)

 

20 минут назад, Delpher-X сказал:

Все подключил, в точности как на картинке. 

Все, разобрался. Только один баг не могу пофиксить. В коде: 

procedure(const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>)
begin
if (Length(AGrantResults) = 1) and (AGrantResults[0] = TPermissionStatus.Granted) then
ShowMessage('Write to File')
end;

end; почему-то подчеркнут красным. Пробовал ставить перед предыдущей строкой ставить точку с запятой, убирать, помещать в отдельный блок begin end; - все бесполезно. 

Отредактировал Delpher-X

Поделиться сообщением


Ссылка на сообщение
  • 0
22 минут назад, Delpher-X сказал:

почему-то подчеркнут красным. Пробовал ставить перед предыдущей строкой ставить точку с запятой, убирать, помещать в отдельный блок begin end; - все бесполезно. 

закр. скобку поставьте ")"...  это анонимная функция... (см. картинку с кодом)

Поделиться сообщением


Ссылка на сообщение
  • 0
1 час назад, slav_z сказал:

закр. скобку поставьте ")"...  это анонимная функция... (см. картинку с кодом)

Точно, не вижу уже ничего. Спасибо! 

Поделиться сообщением


Ссылка на сообщение
  • 0
2 часа назад, slav_z сказал:

такое поведение было у старых андроидов...  теперь необходимо запрашивать разрешение у пользователя прям тогда, когда программе это реально нужно...

Да, еще вопрос. Тот код, который вы запостили вот в этом сообщении, он подходит для запроса любых разрешений для приложения - или только для возможности создавать и изменять файлы и каталоги? 

Поделиться сообщением


Ссылка на сообщение
  • 0

для любых (они должны быть добавлены так же в Uses Permissions для того чтобы попасть в файл манифеста)

Поделиться сообщением


Ссылка на сообщение
  • 0
12 часов назад, slav_z сказал:

для любых (они должны быть добавлены так же в Uses Permissions для того чтобы попасть в файл манифеста)

Тут немного не понял. В вашем коде в uses добавлены только System.Permissions, Androidapi.Helpers, Androidapi.JNI.Os 

Поделиться сообщением


Ссылка на сообщение
  • 0
12 часов назад, slav_z сказал:

в файл манифеста

Толку от этого манифеста, коль скоро нужно запрашивать доступ отдельно и через программный код. 

Поделиться сообщением


Ссылка на сообщение
  • 0
1 час назад, Delpher-X сказал:

Тут немного не понял. В вашем коде в uses добавлены только System.Permissions, Androidapi.Helpers, Androidapi.JNI.Os 

в модуле могут быть два раздела uses:

581777535_.png.6f38babfd7a3eeffce4106c07c0dd20a.png

Поделиться сообщением


Ссылка на сообщение
  • 0
1 час назад, Delpher-X сказал:

Толку от этого манифеста, коль скоро нужно запрашивать доступ отдельно и через программный код. 

если не будет в манифесте, не сможете запросить и программно... это нужно чтобы ОС Android знала какие разрешения может запросить программа... ей это нужно... а сами разрешения у ПОЛЬЗОВАТЕЛЯ! должны запрашиваться в момент когда они действительно  нужны, а не в момент первого запуска программы (как было раньше) ... тут все правильно.. потом разберетесь...

Поделиться сообщением


Ссылка на сообщение
  • 0
В 27.01.2021 в 02:02, slav_z сказал:

если не будет в манифесте, не сможете запросить и программно... это нужно чтобы ОС Android знала какие разрешения может запросить программа... ей это нужно... а сами разрешения у ПОЛЬЗОВАТЕЛЯ! должны запрашиваться в момент когда они действительно  нужны, а не в момент первого запуска программы (как было раньше) ... тут все правильно.. потом разберетесь...

А как разрешения записать в манифест? Или, это делается как-то автоматически? 

Поделиться сообщением


Ссылка на сообщение
  • 0
1 час назад, Delpher-X сказал:

А как разрешения записать в манифест? Или, это делается как-то автоматически? 

Посмотрите выше картинку. Окно Project Options\Uses Permissions.

Поделиться сообщением


Ссылка на сообщение
  • 0
3 минуты назад, slav_z сказал:

Посмотрите выше картинку. Окно Project Options\Uses Permissions.

А, ну да. 

В любом случае, спасибо вам за консультацию. Не хотел бы вас лишний раз напрягать, но быть может, вы могли бы что-то подсказать мне и по вот этому вопросу

Отредактировал Delpher-X

Поделиться сообщением


Ссылка на сообщение

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


  • Похожий контент

    • От Delpher-X
      У меня есть код, который должен скачивать файл с сайта: 
      var LoadFile : TMemoryStream; begin LoadFile := TMemoryStream.Create; IdHTTP1.Get('https://sitename.pro/Folder/FileName.txt', LoadFile); LoadFile.SaveToFile('FileName.txt'); LoadFile.Free; end; Проблема однако в том, что вместо скачивания файла программа выдает: Could not load SSL library, хотя я никакой "SSL library" не просил)). При этом, когда я попробовал скачать файл с сайта работающего по старинке, на http (в отличие от https), все скачалось нормально, то есть проблема явно в данном протоколе. Поиск по Интернету ничего не дал.  
    • От Anatoliy_
      Приветствую
      Подскажите, планируется ли в RAD Studio возможность компиляции Delphi программ  для WebAssembly?
       
    • От Delpher-X
      Есть код для копирования файлов:
      procedure TForm1.Timer2Timer(Sender: TObject); var FileIndex, FileName : String; I : Integer; begin randomize; FileIndex := IntToStr(random(5000)); for I := 0 to ListBox1.Items.Count-1 do begin FileIndex := IntToStr(StrToInt(FileIndex) + 1); FileName := FileIndex + Exp; TFile.Copy(ListBox1.Items[I], FileName); end; Timer2.Enabled := False; end; Когда я его запускаю, все работает, однако постоянно выскакивает сообщение об ошибке: specified file already exists, то есть копируемый файл уже существует. То есть, программа пытается каждый файл скопировать дважды. Вопрос: почему? С чем это связано и как от этого избавиться? 
    • От slav_z
      Есть ли проблемы с запуском приложений на macOS Big Sur у Delphi 10.4.1? Очень страшно обновлять macOS...
    • От Delpher-X
      Здравствуйте. Как указываются пути к каталогам и файлам в Android? Скажем, в Windows я указываю такой путь:  C:/Windows/Folder, а как это делается в Android? Особенно меня интересует, как обратиться к корневому каталогу, для создания там новой папки или файла, в Windows это C:/, или D:/ а тут как? 
    • От destroyer86
      Всем привет, с помощью Java2Op сделал обертку библиотеки получил модуль с интерфейсами.
      Теперь сам вопрос в JavaInterfaces.pas есть описание:
       
      JUsbManagerClass = interface(JObjectClass) ['{1048A6E9-E1B5-4DA5-A168-ED91E8DE5284}'] {class} function _GetACTION_USB_ACCESSORY_ATTACHED: JString; cdecl; {class} function _GetACTION_USB_ACCESSORY_DETACHED: JString; cdecl; {class} function _GetACTION_USB_DEVICE_ATTACHED: JString; cdecl; {class} function _GetACTION_USB_DEVICE_DETACHED: JString; cdecl; {class} function _GetEXTRA_ACCESSORY: JString; cdecl; {class} function _GetEXTRA_DEVICE: JString; cdecl; {class} function _GetEXTRA_PERMISSION_GRANTED: JString; cdecl; {class} function getAccessoryList: TJavaObjectArray<JUsbAccessory>; cdecl;//Deprecated {class} function openAccessory(accessory: JUsbAccessory): JParcelFileDescriptor; cdecl;//Deprecated {class} function openDevice(device: JUsbDevice): JUsbDeviceConnection; cdecl;//Deprecated {class} procedure requestPermission(device: JUsbDevice; pi: JPendingIntent); cdecl; overload;//Deprecated {class} property ACTION_USB_ACCESSORY_ATTACHED: JString read _GetACTION_USB_ACCESSORY_ATTACHED; {class} property ACTION_USB_ACCESSORY_DETACHED: JString read _GetACTION_USB_ACCESSORY_DETACHED; {class} property ACTION_USB_DEVICE_ATTACHED: JString read _GetACTION_USB_DEVICE_ATTACHED; {class} property ACTION_USB_DEVICE_DETACHED: JString read _GetACTION_USB_DEVICE_DETACHED; {class} property EXTRA_ACCESSORY: JString read _GetEXTRA_ACCESSORY; {class} property EXTRA_DEVICE: JString read _GetEXTRA_DEVICE; {class} property EXTRA_PERMISSION_GRANTED: JString read _GetEXTRA_PERMISSION_GRANTED; end; [JavaSignature('android/hardware/usb/UsbManager')] JUsbManager = interface(JObject) ['{6F603A25-E816-4012-9B23-054B428A4A75}'] function getDeviceList: JHashMap; cdecl;//Deprecated function hasPermission(device: JUsbDevice): Boolean; cdecl; overload;//Deprecated function hasPermission(accessory: JUsbAccessory): Boolean; cdecl; overload;//Deprecated procedure requestPermission(accessory: JUsbAccessory; pi: JPendingIntent); cdecl; overload;//Deprecated end; TJUsbManager = class(TJavaGenericImport<JUsbManagerClass, JUsbManager>) end; Что бы получить доступ к методам интерфейса используется следующая конструкция:
      JavaObject := TAndroidHelper.Context.getSystemService(TJContext.JavaClass.USB_SERVICE); FUsbManager := TJUsbManager.Wrap((JavaObject as ILocalObject).GetObjectID); теперь я могу получить доступ к методам JUsbManager, а как получить доступ к методам JUsbManagerClass
      Вот пример кода на Java, который хочу реализовать в Delphi:
      UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE); List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager); if (availableDrivers.isEmpty()) { return; } // Open a connection to the first available driver. UsbSerialDriver driver = availableDrivers.get(0); //Вот тут мы видим что из экземпляра класса мы вызываем openDriver, как это сделать в Delphi UsbDeviceConnection connection = manager.openDevice(driver.getDevice()); Как мы можем заметить этого метода в описании интерфейса нет, но есть в классе, как получить доступ к экземпляру класса?
  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

×
×
  • Создать...