How to download a file from web page displayed by jWebView lazarus / 43-Android ---------------------------------------------------------------------- maurobio · 2023-05-26 12:54 Dear ALL, In my app, I have a jWebView control which opens and display a web page (of course!)  That page has some linked spradsheet files (in XLSX format) which however I cannot downloading by just clicking on them - obviously some code is needed for that. So, here are my questions: First of all, is it possible to do that (i.e., downloading a file from a web page using jWebView)?If it is possible, how can it be done?Where should the downloaded file is stored?and last, but not least, how can my app call whatever installed app that can open XLSX files? (This would be much simpler and efficient than attempting to embed in my app the reading and displaying of such files, which did not work anyway). Thanks in advance! With best regards, ---------------------------------------------------------------------- jmpessoa · 2023-05-26 22:48 1. You can try jHttpClient, see some demos... 2. There are some demos "how to" download a file 3. Maybe in default  "Internal App Storage" 4. Look for "Intents" demos ---------------------------------------------------------------------- maurobio · 2023-05-27 12:58 Hi, @jmpessoa! I will take a look at the demos, they usually are always much useful. Thanks a lot! Best regards, ---------------------------------------------------------------------- maurobio · 2023-05-31 11:55 Dear ALL, I have been still unable to find out how to get the link being clicked on jWebView. Here is the sequence of steps showing what I want to achieve: 1) A webpage is displayed in a jWebView; this page has some links to other pages as well as links to files (in text, xlsx, pdf, whatever); 2) When a link to another page is clicked, the jWebView component automatically handles it and opens the linked page; but if the clicked link points to a file, nothing happens. Obviously, some code must be written to handle this. 3) So, here is my question (again): how do I get the clicked link on jWebView, so that I can handle its download (via an jHttpClient component) and then open it (via an Intents component)? Any hints (with example code if possible)? Many thanks in advance! With best regards, ---------------------------------------------------------------------- c4p · 2023-05-31 18:28 I'm using jWebView in my project for some single site stuff and have pondered this very thing. There's no OnClick event (yet) to make things a bit easier but what you could do is use the URL string variable in OnStatus of jWebView and monitor for a change of the URL variable and then pass that variable to jHttpClient to download, not very elegant but should be easy enough to catch as long as you know the main site URL so you can monitor for the change. It may be tricky to do this with dynamic URLs but if you know roughly what filename extensions you're looking for to download you could filter out the rest easily enough, I would have thought. You can also use CanNavi (boolean) in the same event to check for a valid URL too? if that's what it does (need to test that though). To handle the file download you can either use the code in the AppDownloadManagerDemo1 Demo which you can use to download multiple files visually which will Notify to the device or a basic jHttpClient download with no jBroadcastReceiver, I have used this demo in my app to do some basic multiple downloads to get some images down that match up with internal IDs in the app, but also used a basic jHttpClient download direct with no jBroadcastreceiver. I tested linking to a zip file and it does register in the URL variable OK in jWebView, so should be easy enough to implement. Just add the following to the OnStatus method to show the URL on screen when you click a link, then you can play with that variable: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i showmessage(URL); Should be fairly straightforward to use an intent as long as you know the package name, I will dig out my old delphi code when I used an intent to open Chrome/Firefox/Brave etc from a URL and try something tonight all things being well. I hope this helps, if you want some code I can have a bash later, if you think this will do? ---------------------------------------------------------------------- maurobio · 2023-05-31 19:56 Hi, @c4p! Thanks a lot for your clear and very comprehensive answer! It deserves a longer reply, as follows: QuoteThere's no OnClick event (yet) to make things a bit easier but what you could do is use the URL string variable in OnStatus of jWebView and monitor for a change of the URL variable and then pass that variable to jHttpClient to download, not very elegant but should be easy enough to catch as long as you know the main site URL so you can monitor for the change. It may be tricky to do this with dynamic URLs but if you know roughly what filename extensions you're looking for to download you could filter out the rest easily enough, I would have thought. That's exactly what I had in mind, but could not see how to doing it because, as you pointed out, there is no OnClick event in jWebView; however, the solution you suggest seems to do the trick nicely! In my app, I will always know the main site URL (it is a fixed one). I will also always know the filename extensions I am looking for downloading (it is also a fixed one). QuoteQuoteTo handle the file download you can either use the code in the AppDownloadManagerDemo1 Demo which you can use to download multiple files visually which will Notify to the device or a basic jHttpClient download with no jBroadcastReceiver, I have used this demo in my app to do some basic multiple downloads to get some images down that match up with internal IDs in the app, but also used a basic jHttpClient download direct with no jBroadcastreceiver. I had already took a very quick glance at jHttpClient, but of course will need to look at it more closely - without having a way to first get the filename to be downloaded, it did not make sense to delve in it. I will try the AppDownloadManagerDemo1 to begin with (although it handles multiple files and my app will handle only one file at a time, that is, at each user click!). QuoteI tested linking to a zip file and it does register in the URL variable OK in jWebView, so should be easy enough to implement. Just add the following to the OnStatus method to show the URL on screen when you click a link, then you can play with that variable: I will try this ASAP! QuoteShould be fairly straightforward to use an intent as long as you know the package name, I will dig out my old delphi code when I used an intent to open Chrome/Firefox/Brave etc from a URL and try something tonight all things being well. I understand that by "package" you men the app "associated" with the extension of the file which will be downloaded and then opened by said app? Is it really necessary to know the name of the package in advance? As I understood of Android "intents", any app already available in the device which able to handle that file type (eg., a pdf) is automatically invoked (or if there is more then one app that can handle such files, the user is presented with the choices of what app to use). QuoteQuoteI hope this helps, if you want some code I can have a bash later, if you think this will do? This has helped a lot, believe me! Your comprehensive and thoughtful answer truly contributed to make things clear to me. I will now test your suggestions here, using the code provided with the LAMW demos. I will update this thread reporting my eventual progress.  BTW, once it is completed and fully working, I will make the source code of my app freely available via GitHub, so that other developers can use to avoid looking for the answers to these needs. With warmest regards, ---------------------------------------------------------------------- c4p · 2023-05-31 20:09 A rough idea to download a file from jWebView after you click a url to download a file: You will need these components added to test code below: jWebView jBroadcastReceiver jDownloadManager Downloaded file will go into your 'Downloads' folder. You can of course use jHttpClient to download the file directly if you want to avoid using the DownloadManager, this is just an example. Add this to a button in your project to load the test file download page: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i WebView1.Navigate('https://getsamplefiles.com/sample-archive- files/zip'); Add to the 'OnStatus' event of WebView1. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TTest.WebView1Status(Sender: TObject; Status: TWebViewStatus;  URL: String; var CanNavi: Boolean);var res : TAndroidResult; SlashPos : Integer; URLFileName : String;beginif (containstext(URL, '.zip')) then //Can check in an array if you want with a bunch of extensions or another way? begin  SlashPos := LastDelimiter('/', URL); //Get the last occurrence of slash in the URL  URLFilename := AnsiRightStr(URL, length(URL)-Slashpos); //Get filename after the last slash in the URL using SlashPos position  BroadcastReceiver1.RegisterIntentActionFilter (DownloadManager1.GetActionDownloadComplete()); //Register intent  DownloadManager1.SaveToFile(URLFIlename); //What your downloaded file will be called, let's use the URL filename (there may be a method to get the filename?)  res:= DownloadManager1.Start(URL); //Start the download   //Use res to check for successful download or fail  if (res = RESULT_OK) then   begin    showmessage('Download successful');   end    else     showmessage('Download FAILED!'); end; end; I will try some intent code to open a package with a specific file extension later, yes, I mean the associated app, but you may need to do this with an intent and may need the package name if the helper cannot find the app, also allows you to set a specific app, Excel on Android is something like com.microsoft.office.excel, I recommend the Package name app https://play.google.com/store/search?q=package%20name &c=apps&hl=en_IN&gl=US from the Play Store, used it a bit in the past, it shows all your installed app package names. If you set the Intent MIME type it will open with the default app. Some basic Intent code to open the default ZIP app on your device, you would have to pass the File probably via IntentManager1.SetDataUri? to get say WinZip to open the file with package. Add jIntentManager to your Project. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i IntentManag er1.SetAction('android.intent.action.VIEW');IntentManager1.SetMimeType ('application/zip');IntentManager1.StartActivity(); More MIME types here: https://android.googlesource.com/platform/external/mime- support/+/9817b71a54a2ee8b691c1dfa937c0f9b16b3473c/mime.types ---------------------------------------------------------------------- maurobio · 2023-06-01 19:27 Hi, @c4p! Here are  some good news... Using the code you provided, I have been able to download a file when a link to it is clicked (I used my "live" website - i.e., that which my production app will present to the user - and it worked fine). But (there is always a "but"!) I have not (yet) been able to open the downloaded file using the Intent component. The MIME type is correctly defined, because upon calling IntentManager.StartActivity(), the apps installed in my device that can handle the intended file type (in that case, an Excel spreadsheet) are correctly displayed to the user choose one of them to open the file). Just afterwards, an error arises. I suspect the IntentManager,SetDataUri() method is not being correctly called, because besides the error which arises, jWebView opens the website in the default browser, instead of opening the spreadsheet in the associated app. Here is the modified code of the WebView OnStatus event: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TAndroidModule1.jWebView1Status(Sender: TObject; Status: TWebViewStatus;  URL: string; var CanNavi: boolean);var  res: TAndroidResult;  SlashPos: integer;  URLFileName: string;begin  //ShowMessage(URL);  if (ContainsText(URL, '.xlsx')) then    //Can check in an array if you want with a bunch of extensions or another way?  begin    SlashPos := LastDelimiter('/', URL); //Get the last occurrence of slash in the URL    URLFilename := AnsiRightStr(URL, Length(URL) - Slashpos);    //Get filename after the last slash in the URL using SlashPos position    jBroadcastReceiver1.RegisterIntentActionFilter(      jDownloadManager1.GetActionDownloadComplete()); //Register intent    jDownloadManager1.SaveToFile(URLFIlename);    //What your downloaded file will be called, let's use the URL filename (there may be a method to get the filename?)    res := jDownloadManager1.Start(URL); //Start the download    //Use res to check for successful download or fail    if (res = RESULT_OK) then    begin      ShowMessage('Download of' + sLineBreak + URL + sLineBreak + 'successful');    end    else      ShowMessage('Download of' + sLineBreak + URL + sLineBreak + 'FAILED!');  end;   //jIntentManager1.SetAction(iaView);  //or 'android.intent.action.VIEW'  jIntentManager1.SetAction('android.intent.action.VIEW');  jIntentManager1.SetMimeType('application/vnd.openxmlformats- officedocument.spreadsheetml.sheet');  jIntentManager1.SetDataUri(jIntentManager1.ParseUri(URL)); // <-- This seems to be faulty!  jIntentManager1.StartActivity();end;   Any further hints? Thanks a lot! With warmest regards, ---------------------------------------------------------------------- c4p · 2023-06-03 06:43 Got close but was unable to get the application to recognise the file, not sure what's going on there, why it's not opening the file. See if you get the same: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i IntentManag er1.SetDataAndType('content://'+Self.GetEnvironmentDirectoryPath(dirSd Card) + '/Download/'+URLFileName,'application/vnd.ms-excel'); More info: https://forum.lazarus.freepascal.org/index.php/topic,46621. msg333891.html ---------------------------------------------------------------------- maurobio · 2023-06-03 14:07 Hi, @c4p! It does not work. Notice that the downloaded file goes into the device's main storage (dirDownloads) and not into the device SD card (dirSdCard) which may not exist. I have also tried: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i jIntentManager1.SetDataAndType('content://' + Self.GetEnvironmentDirectoryPath(dirDownloads) + '/' + URLFilename, 'application/vnd.ms-excel'); and Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i jIntentManager1.SetDataAndType('content://' + Self.GetEnvironmentDirectoryPath(dirDownloads) + '/' + URLFilename, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); which does not work either. Right now, I am searching StackOverflow for how to open an associated file on Android using Intents; there are many suggestions, all of them of course in Java, but a few of them even make sense and are worth a try. With warmest regards, ---------------------------------------------------------------------- maurobio · 2023-06-03 18:32 Hi, @c4p! Something like this do the trick in Java: Code: Java  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i private void openFile(String file) {try {    Intent i = new Intent(Intent.ACTION_VIEW);    i.setDataAndType(Uri.fromFile(new File(file)), "application/pdf");//this is for pdf file. Use appropreate mime type    startActivity(i);} catch (Exception e) {             Toast.makeText(this,"No pdf viewing application detected. File saved in download folder",Toast.LENGTH_SHORT).show();}} But what the heck is type "uri"? And does the method fromFile() exist in LAMW? There some interesting variations to the code above, but they all declare a variable of type "uri" and call a fromFile() method. With warmest regards, ---------------------------------------------------------------------- jmpessoa · 2023-06-03 23:44 QuoteBut what the heck is type "uri"? And does the method fromFile() exist in LAMW? There some interesting variations to the code above, but they all declare a variable of type "uri" and call a fromFile() method. LAMW: i.SetDataAndType(i.ParseUri('file://'+_environmentDirectoryPath+'/'+ _fileName), "application/pdf") ---------------------------------------------------------------------- maurobio · 2023-06-04 12:04 Hi, @jmpessoa! Shouldn't it be: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i jIntentManager1.SetDataAndType(jIntentManager1.ParseUri('file://' + Self.GetEnvironmentDirectoryPath(dirDownloads) + '/' + URLFilename), 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); "_environmentDirectoryPath" and "_fileName" are not declared anywhere in the code. Besides, I want to open xlsx files, not pdf's. Anyway, it not works... not even an error message is issued. The file not opened in the associate app. Best regards, ---------------------------------------------------------------------- maurobio · 2023-06-04 14:01 Hi, I really do fail to understand why something as simple as the code below does not work! Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i jIntentMana ger1.SetAction('android.intent.action.VIEW');jIntentManager1.SetDataAn dType(jIntentManager1.ParseURI('file://' + Self.GetEnvironmentDirectoryPath(dirDownloads) + '/' + URLFilename), 'application/vnd.openxmlformats- officedocument.spreadsheetml.sheet');jIntentManager1.StartActivity; The Uniform Resource Identifier is being correctly created and points to the correct path, as can be easily seen by calling Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i ShowMessage('file://' + Self.GetEnvironmentDirectoryPath(dirDownloads) + '/' + URLFilename); What is wrong?  Best regards, ---------------------------------------------------------------------- jmpessoa · 2023-06-04 16:59 Test it for "application/pdf"  first!    Otherwise,  You can try a direct jForm method:  (Test it for "application/pdf"  first , too!)    Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i    Self.StartDefaultActivityForFile(_filePath, _mimeType);  but: QuoteAndroid 11  - Api 30  (and up) has restricted developers to access devices folders (ex: "Download, Documents, ..., etc")" the demo is here: "AppPublicFoldersAccessDemo1' ---------------------------------------------------------------------- maurobio · 2023-06-04 17:51 Hi, @jmpessoa! QuoteTest it for "application/pdf"  first! Why should it work with a specific mime type and not with any other? This demands a clear, comprehensive explanation. QuoteAndroid 11  - Api 30  (and up) has restricted developers to access devices folders (ex: "Download, Documents, ..., etc")" If the problem with opening the downloaded file is caused by such "restrictions", why is it that my app can save files in the Download folder without any hassles? An why is it that the OS does not issue any error or warning messages when I attempt to open a file using an Intent? Furthermore (because there is always "more"!) why is it that thousands of apps can easily save and open files in the Downloads folder (notwithstanding the Android version running in the device)? Anyway, why should this be expected to work with "pdf" files, but not "xlsx" ones? Quotethe demo is here: "AppPublicFoldersAccessDemo1' Referring constantly to code deeply buried in the LAMW demos - in the vague hope that one can see a solution there - does not really helps. Working fragments of code, posted here, this is what helps. Best regards, ---------------------------------------------------------------------- jmpessoa · 2023-06-04 18:04 QuoteWhy should it work with a specific mime type and not with any other? yes, if it work,  it wil work  with any other mime type.... but for test....... ---------------------------------------------------------------------- maurobio · 2023-06-04 18:29 Hi, @jmpessoa! Quoteyes, if it work,  it will work  with any other mime type.... but for test....... Sorry, but this looks suspiciously like "voodoo programming" (https://www.techopedia.com/definition/22860/voodoo-programming), which just leads one to wasting time and suffering unnecessary rises in blood pressure. Best regards, ---------------------------------------------------------------------- jmpessoa · 2023-06-04 18:35 No,that is "programming" ..... you have a complex mime type:  "vnd.openxmlformats- officedocument.spreadsheetml.sheet", do you know if this is correct?  I don't know.... So, test the simple, after the complex.... ---------------------------------------------------------------------- maurobio · 2023-06-04 19:33 Hi, @jmpessoa! QuoteNo,that is "programming" ..... Per the definition of "voodoo programming": QuoteVoodoo programming refers to the practice of coding according to superstition, guesses, or anything other than logic. Voodoo programming is a rather broad term for situations where a programmer uses a piece of code without truly understanding how it works. ... we are clearly practising it. Quoteyou have a complex mime type:  "vnd.openxmlformats- officedocument.spreadsheetml.sheet", do you know if this is correct?  I don't know.... Of course it is "correct", as much as any other (see the list of available mime types here: https://android.googlesource.com/platform/external/mime- support/+/9817b71a54a2ee8b691c1dfa937c0f9b16b3473c/mime.types). What a purely subjective impression of "complexity" has to do with it? BTW, see here an example in Java of the use of that mime type: Code: Java  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Intent intent;            String[] mimetypes =                { "application/vnd.ms-excel", // .xls"application/vnd.openxmlformats- officedocument.spreadsheetml.sheet" // .xlsx                       };         intent = new Intent(Intent.ACTION_GET_CONTENT); // or use ACTION_OPEN_DOCUMENT        intent.setType("*/*");        intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);        intent.addCategory(Intent.CATEGORY_OPENABLE);  Best regards, ---------------------------------------------------------------------- jmpessoa · 2023-06-04 19:39 Quotesee here an example in Java of the use of that mime type... Good! Now I know about! Thank you! ---------------------------------------------------------------------- maurobio · 2023-06-04 19:53 Hi, jmpessoa! There are many (presumably useful) examples in Java of opening files with associated apps in StackOverflow and other websites: https://stackoverflow.com/questions/63482335/intent-to-read-both-xls- and-xlsx-files-in-android https://stackoverflow.com/questions/31377367/how-to-open-downloaded- file-in-android-with-default-availabe-application-in-andr https://stackoverflow.com/questions/7239996/android-downloadmanager- api-opening-file-after-download https://stackoverflow.com/questions/36766483/after-download-how-to- open-downloaded-file https://ashumaurya-9286.medium.com/how-to-open-a-excel-file-in- android-programmatically-8295b932b9ef https://medium.com/@eliothijanoc/simple-way-to-download-and-read- files-on-android-api-28-3557e6d240e5 Best regards, ---------------------------------------------------------------------- jmpessoa · 2023-06-04 20:31 Ok. I will try! until then check your project file "AndroidManifes.xml", look for: Quote                        and try to add (one by one) them... ---------------------------------------------------------------------- c4p · 2023-06-04 20:33 OK, all of these mime types work for me using StartDefaultActivityForFile, but NOT to the root /Download directory or dirInternalAppStorage but work fine from the project Download directory (dirDownloads), PDF and Excel file open direct from the filesystem without issue. Can download fine to /Download normally using jDownloadManager though. Check this again maurobio to see if it works? thank you. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Self.StartD efaultActivityForFile(Self.GetEnvironmentDirectoryPath(dirDownloads)+' /file.pdf', 'application/pdf'); Self.StartDefaultActivityForFile(Self. GetEnvironmentDirectoryPath(dirDownloads)+'/file.xlsx','application/vn d.ms-excel');Self.StartDefaultActivityForFile(Self.GetEnvironmentDirec toryPath(dirDownloads)+'/file.xlsx','application/vnd.openxmlformats- officedocument.spreadsheetml.sheet'); ---------------------------------------------------------------------- maurobio · 2023-06-04 20:45 Hi, @jmpessoa! My project AndroidManifest.xml already included much of the flags you have suggested; adding the others did not made any difference. I doubt this is a problem of permissions, because: (i) I can save (write) to the main storage Downloads folder without problems; and (ii) I get no error or warning messages from Android - in fact, nothing happens after the file is correctly downloaded (when it should then be opened in the associated application). Since you feel at will with demos, I can suggest you create a small sample with two buttons, one for displaying a XLSX file, the other for displaying a PDF file; put these files in the your main storage Downloads folder and let's see what happens. As a start, I attach an (incomplete) app based on one of the LAMW demos. If it works, the problem is solved and you will be able to add another useful demo to the repository (therefore aiding others in the future). Hope this helps. With best regards, ---------------------------------------------------------------------- jmpessoa · 2023-06-04 21:02 Well, you "demo" not handle permission by the user.... what about? ---------------------------------------------------------------------- maurobio · 2023-06-04 21:08 Hi, @c4p! QuoteOK, all of these mime types work for me using StartDefaultActivityForFile, but NOT to the root /Download directory or dirInternalAppStorage but work fine from the project Download directory (dirDownloads), PDF and Excel file open direct from the filesystem without issue. Can download fine to /Download normally using jDownloadManager though. Your suggestions did not work because, if I did understand correctly, the file is (correctly) downloaded to the main storage but (always a "but"!) it can only be opened if it is downloaded to the app Download folder. Here is the situation of my code until now, it need to be modified so that the file can be downloaded and opened without issues! Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TAndroidModule1.jWebView1Status(Sender: TObject; Status: TWebViewStatus;  URL: string; var CanNavi: boolean);var  res: TAndroidResult;  SlashPos: integer;  URLFileName: string;begin  if ExtractFileExt(URL) = '.xlsx'    //Can check in an array if you want with a bunch of extensions or another way?  begin    SlashPos := LastDelimiter('/', URL); //Get the last occurrence of slash in the URL    URLFilename := AnsiRightStr(URL, Length(URL) - Slashpos);   //Check if file already exists to avoid downloading multiple versions of it    if not FileExists(self.GetEnvironmentDirectoryPath(dirDownloads) +      '/' + URLFilename) then    begin      //Get filename after the last slash in the URL using SlashPos position      jBroadcastReceiver1.RegisterIntentActionFilter(        jDownloadManager1.GetActionDownloadComplete()); //Register intent    jDownloadManager1.SaveToFile(URLFIlename);      //What your downloaded file will be called, let's use the URL filename (there may be a method to get the filename?)      res := jDownloadManager1.Start(URL); //Start the download      //Use res to check for successful download or fail      if (res = RESULT_OK) then        ShowMessage('Download of' + sLineBreak + URL + sLineBreak + 'successful')      else        ShowMessage('Download of' + sLineBreak + URL + sLineBreak + 'FAILED!');    end;     jIntentManager1.SetAction('android.intent.action.VIEW');   // This does not work (i.e., nothing happens)    StartDefaultActivityForFile(Self.GetEnvironmentDirectoryPath(      dirDownloads) + ExtractFileName(URLFilename),      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');  end;end;   With best regards, ---------------------------------------------------------------------- maurobio · 2023-06-04 21:11 Hi, @jmpessoa! QuoteWell, you "demo" not handle permission by the user.... what about? This "demo" is incomplete and not tested; I provided it just a starting point. Anyway, see the previous message by c4p. Best regards, ---------------------------------------------------------------------- jmpessoa · 2023-06-04 23:27 @c4p Quotebut NOT to the root /Download directory or dirInternalAppStorage but work fine from the project Download directory (dirDownloads) Yes, for Android 11 (and Up) .... this is it!  It is very likely that the solution suggested so far works only for Android < 11 .... Hi,  c4p! Please, study the demo  "AppPublicFoldersAccessDemo1",  maybe you can make a new one much simpler to meet the @maurobio requirement... (that is, I'm guessing you already understand what actually solves the question.....) ---------------------------------------------------------------------- maurobio · 2023-06-05 00:04 Hi, @jmpessoa, @c4p! Thanks a lot for your hopefully inexaustible patience in helping me!  QuoteIt is very likely that the solution suggested so far works only for Android < 11 .... Probably Android < 10 because it does not work for me (my device runs Android 10). I have not looked at the demo suggested by jmpessoa but hope to do it by tomorrow. Hope a solution to this annoying problem come up soon... With warmest regards ---------------------------------------------------------------------- c4p · 2023-06-05 18:52 It's definitely a permissions issue, if you go to your app in Settings on Android, go to Apps select your app and go to Permissions, then Files and Media, it's probably set to 'Allow access to media only' select 'Allow management of all files'. You should now be able to access /Download folder and open xlsx files using StartDefaultActivityForFile etc. I am using Android 12, so manually granting your app all files permissions may be slightly different on your device. This works now on my device after I set the permissions manually on the device to Allow management of all files: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Self.StartD efaultActivityForFile(Self.GetEnvironmentDirectoryPath(dirSdCard)+'/Do wnload/'+URLFilename,'application/vnd.ms-excel'); Of course, this is a proof of concept to show it's a permissions issue, but you now have to grant access to this permission via code. I will look for the code to grant permission to all file via code, probably ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION via an intent. ---------------------------------------------------------------------- maurobio · 2023-06-05 19:19 Hi, @c4p! Thanks, but this gets more and more (there is always a "but", and several "mores") weirder... First of all, I can't understand the permissions issue I find especially difficult to understand why this crappy, half-breed operating system which is called 'Android' allows to download (i.e., writing) files to the damned main storage device but does not allow to open (i.e., reading) the very same files! This defies all logic! Anyway, isn't there one or more ways of granting permissions via code? Thousands of apps ask users for permissions before running the first time, why this very silly app of mine cannot do the same? And more (!): in your code you are using the SDCard, bur the problem is not supposed to be with the main storage device? What if the poor user doesn't have a SDCard? And yet more: if the problem is really one of the permissions, why not simply download the file to a 'public' folder or something where the downloaded files can be opened without hassle? I am totally confused! With best regards, ---------------------------------------------------------------------- c4p · 2023-06-05 19:38 If it was me, I would download the file to the project folder, unless you have a reason why you need to download to /Download, there may be a valid reason why you want to do this, easy access to files for the user etc. I personally find dealing with permissions a bind/messy and always keep within the confines of my project folder, less problems for you and the user, some people panic when they see a permissions box in an app. Now, if you could change the JDownloadManager download path to your project path it would be problem solved, I honestly don't know if you can, but I will check, maybe jmpessoa knows. dirSDCard is a legacy assignment and actually points to the root of the devices storage. I think something like dirextSDCard was an actual sdcard. I agree with you about Android but it has gone this way because of exploits and people not knowing what's happening with their data, so it gives the user more control over their data, an absolute pain for anyone coding an android though! Now to play with jDownloadManager! ---------------------------------------------------------------------- maurobio · 2023-06-05 19:51 Hi, @c4p! Thanks, as always, for your clear and comprehensive explanation! From my part, I am also attempting to do something to help ourselves - I am developing a "demo"as jmpessoa likes, sort of a simplified version of my own app. I presume it will be much easier for us to work on the basis of it. I will post it in an attachment in the next half-hour. With warmest regards, ---------------------------------------------------------------------- maurobio · 2023-06-05 20:12 Hi, @cp4! As promised, here is my complete "demo" ( ) app, which is a striped- down version of my production app. When executed, it simply displays a pre-defined webpage with three links to files in XLSX, XLS, and PDF formats (these are the only types my production app will have to deal with). Clicking on a link causes the file to be download (it it does not exist) and then the file is (or should be!) opened in the associated app. In principle, it does not matter in what folder the downloaded file will be stored, provided that the user can open it in the associated app. Hope we can use this code as a testbed to finally come up with a complete working solution. With warmest regards, ---------------------------------------------------------------------- jmpessoa · 2023-06-05 20:25 QuoteNow to play with jDownloadManager!... Yes! the demo " AppDownloadManagerDemo1"  has all we need....  (to  access the URI of the location where was saved your file, handle the event "OnReceiver"  as shown in the demo.....) @maurobio Please, check what you got on "URL" parameter  received from "jWebView1Status"  event... if  the link  is all ok,  then send me the link to a very simple file.... (if private,  sent it by message or e-mail....) ---------------------------------------------------------------------- maurobio · 2023-06-05 20:31 Hi, @jmpessoa! Please see the demo app I attached to my previous post in reply to @cp4! It is a shortened version of my production app - if we get it working, so our problems are solved (until the next ones appear)! With best regards, ---------------------------------------------------------------------- c4p · 2023-06-05 20:32 Actually, I think DownloadService is probably better (see AppDownloadServiceDemo1) as I could not get jDownloadManager outside the confines of the /Download directory (this may be by design though), DownloadService will download direct to your project folder, have a look at this code and adapt for your own: Add jBroadcastReceiver Add jDownloadService Change YOURAPPNAME to your app name, whatever your project folder is called, probably. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  BroadcastR eceiver1.RegisterIntentActionFilter('org.lamw.YOURAPPNAME.DOWNLOAD_REC EIVER'); //Register intent for Broadcast receiver DownloadService1.Sav eToFile(Self.GetEnvironmentDirectoryPath(dirDownloads), 'sample-1.xlsx'); //Save file to project Download directory DownloadSe rvice1.Start('https://getsamplefiles.com/download/xlsx/sample-1.xlsx', 'org.lamw.YOURAPPNAME.DOWNLOAD_RECEIVER'); //Start the download Put below into OnReceiver event of jBroadcastReceiver. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  Self.Start DefaultActivityForFile(Self.GetEnvironmentDirectoryPath(dirDownloads) + '/sample-1.xlsx','application/vnd.ms-excel'); //Start the downloaded file using correct mime type @maurobio probably something like this for your app using excel mime type, obviously you would need to do a check to see if the downloaded file is excel, pdf, txt extension etc. and assign correct mime type for the downloaded file type. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  BroadcastR eceiver1.RegisterIntentActionFilter('org.lamw.YOURAPPNAME.DOWNLOAD_REC EIVER'); //Register intent for Broadcast receiver DownloadService1.Sav eToFile(Self.GetEnvironmentDirectoryPath(dirDownloads), URLFilename); //Save file to project Download directory DownloadService1.Start(URL, 'org.lamw.YOURAPPNAME.DOWNLOAD_RECEIVER'); //Start the download Put below into OnReceiver event of jBroadcastReceiver. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  Self.Start DefaultActivityForFile(Self.GetEnvironmentDirectoryPath(dirDownloads) + '/'+URLFilename,'application/vnd.ms-excel'); //Open the downloaded file using correct mime type/app You shouldn't need permissions, although you can add permission checks if you wish, but not needed really as you will have full access to the Download directory in your own project area. ---------------------------------------------------------------------- maurobio · 2023-06-05 20:42 Hi, @cp4! I hope we are getting there... Quote@maurobio probably something like this for your app using excel mime type, obviously you would need to do a check to see if the downloaded file is excel, pdf, txt extension etc. and assign correct mime type for the downloaded file type. I added these checks to the demo app I sent you in a previous reply. It looks like with a few minor modifications we can cat this thing done - but the demo ( ) is always in the details... QuoteChange YOURAPPNAME to your app name, whatever your project folder is called, probably. An now, for a very funny question! What is exactly the name of my app?  In the case of the demo I sent you, it is called ShowDownApp, but in the device it is titled AppLAMWProject1. Is it suffering from an identity crisis? With warmest regards, ---------------------------------------------------------------------- jmpessoa · 2023-06-05 20:49 QuoteCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  DownloadSe rvice1.Start('https://getsamplefiles.com/download/xlsx/sample-1.xlsx', 'org.lamw.YOURAPPNAME.DOWNLOAD_RECEIVER');  Self.StartDefaultActivityF orFile(Self.GetEnvironmentDirectoryPath(dirDownloads) + '/sample-1.xlsx','application/vnd.ms-excel'); No!  Put  this code in "jBroadcastReceiver1Receiver"  (as shown in "demo"...): Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  Self.Start DefaultActivityForFile(Self.GetEnvironmentDirectoryPath(dirDownloads) + '/sample-1.xlsx','application/vnd.ms-excel'); That is: the result from "DownloadService"  or "DownloadManager"   need be handled by events..... ---------------------------------------------------------------------- c4p · 2023-06-05 20:59 Yes, of course, that would be better, I have amended the post. Too much speed  Put below into OnReceiver event of BroadcastReceiver. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  Self.Start DefaultActivityForFile(Self.GetEnvironmentDirectoryPath(dirDownloads) + '/sample-1.xlsx','application/vnd.ms-excel'); ---------------------------------------------------------------------- maurobio · 2023-06-05 21:13 Hi, @c4p, @jmpessoa! Can all these modifications be implemented in the "demo" app I sent in a previous reply? This will make things clear (to me, at least). Thanks in advance! With warmest regards, ---------------------------------------------------------------------- maurobio · 2023-06-05 22:55 Hi, @c4p, @jmpessoa! I would like to explore another option which seems to be simpler and does not require using more components (like DownloadService, etc.) Would it be possible to simply copy the downloaded file (in the main storage device 'Downloads' folder) to a 'public', temporary directory (other than that of the app itself)?? The copied file could be opened and then deleted when the app closes - but the original download file would be preserved in the Downloads folder in case the user would like to keep it for later uses. If this is possible, what folder should be used for this trick? With best regards, ---------------------------------------------------------------------- jmpessoa · 2023-06-06 03:19 hi, maurobio just a side note:  do you need save the file? or only open/read  it? ---------------------------------------------------------------------- maurobio · 2023-06-06 11:16 Hi, @jmpessoa! Quotejust a side note:  do you need save the file? or only open/read  it? I want both. When a user visits a website and clicks on a linked file, her/he expects to have the file opened in the associated app and to have it saved in the Downloads directory. I want that my app offers the user that very same experience. Best regards, ---------------------------------------------------------------------- maurobio · 2023-06-06 11:26 Hi, @c4p, @jmpessoa! I tried this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i if not DirectoryExists(TempDir) then    begin      if not CreateDir(TempDir) then      begin        ShowMessage('Error creating temporary directory');        Exit;      end      else      CreateDir(TempDir);      CopyFile(ExtractFileName(URLFilename), TempDir + ExtractFilename(URLFilename));    end; where "TempDir" is a string constant declated as: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i const  TempDir = '/Android/data/org.lamw.showdown/files/'; But this does not work either - no directory is created, no error message is issued, and of course no file is copied to anywhere. I don't even see something like '/Android/data/org.lamw.MYAPPNAME' in my directory tree (either in the main storage or the SD card). Unless you wizards appear with a complete piece of software which fully works, hopefully based on the demo I provided in a previous post, I gave up. I expected this to be an exceedingly simple matter, but so far it has turned out to be only a wasteful nightmare.  Maybe some things are better done in Java, or not at all. With warmest regards, ---------------------------------------------------------------------- maurobio · 2023-06-07 12:35 Hi, @c4p, @jmpessoa! Since I have not heard any more from you, it is possible that you had gave up too or considered that the problem has been solved - which, for me, has been not. I stumbled upon this: https://medium.com/@eliothijanoc/simple-way-to- download-and-read-files-on-android-api-28-3557e6d240e5, which as far as I could understand (the problem is not English, it is Java!) provides an easier solution to accessing files in the Download directory of Android versions 10+. And if it can be done in Java, I can see no good reason why it cannot be done in LAMW as well. As an aside, I would like to ask: should my app create a directory somewhere in the file system like "org.lamw.myapp" (where "myapp" is the name of my app)? I could not find any such directory anywhere. s it created only programmatically? I will do keep trying... With best regards, ---------------------------------------------------------------------- maurobio · 2023-06-07 14:31 Hi, @c4p, @jmpessoa! Just to sum up my attempts up to now considering your recent comments & suggestions QuoteIt's definitely a permissions issue, if you go to your app in Settings on Android, go to Apps select your app and go to Permissions, then Files and Media, it's probably set to 'Allow access to media only' select 'Allow management of all files'. My device has no such "Files and Media" option under Settings/Apps and Notifications/Permissions, but it has instead a "Memory" option which I checked to give permission. QuoteThis works now on my device after I set the permissions manually on the device to Allow management of all files: Self.StartDefaultActivityForFile(Self.GetEnvironmentDirectoryPath(dirS dCard)+'/Download/'+URLFilename,'application/vnd.ms-excel'); It does not work for me. Result is the same: nothing happens, no error or warning message is issued. Quote @maurobio probably something like this for your app using excel mime type, obviously you would need to do a check to see if the downloaded file is excel, pdf, txt extension etc. and assign correct mime type for the downloaded file type. BroadcastReceiver1.RegisterIntentActionFilter('org.lamw.YOURAPPNAME.DO WNLOAD_RECEIVER'); //Register intent for Broadcast receiver DownloadService1.SaveToFile(Self.GetEnvironmentDirectoryPath(dirDownlo ads), URLFilename); //Save file to project Download directory DownloadService1.Start(URL, 'org.lamw.YOURAPPNAME.DOWNLOAD_RECEIVER'); //Start the download Using DownloadService instead of DownloadManager as before does not change anything. The file is correcelty downloaded, but still nothing happens - no warnings or error messages. QuotePut below into OnReceiver event of BroadcastReceiver. Self.StartDefaultActivityForFile(Self.GetEnvironmentDirectoryPath(dirD ownloads) + '/sample-1.xlsx','application/vnd.ms-excel'); Putting that code in the OnReceiver event does not changes anything. Again, not happens: no warnings, no error messages. Last, but not least, jmpessoa stated that: QuoteYes! the demo " AppDownloadManagerDemo1"  has all we need.... Not, it does not. The demo downloads an image from a website, but then displays it on a jImageView component, when if fact what "we need" would be the image opened by an external app. If that demo could be modified to do this, then I suppose it could be realistically used as the bases of a solution to the problem. Hope this helps (but do not believe it will). Best regards, ---------------------------------------------------------------------- jmpessoa · 2023-06-07 20:13 QuoteThe demo downloads an image from a website, but then displays it on a jImageView component, when if fact what "we need" would be the image opened by an external app.... Replace the jImageView  reference by: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     IntentManager1.SetAction(iaView);    IntentManager1.SetDataAndType(jDownloadManager1.GetFileUri(), 'application/pdf');  //application/vnd.ms-excel ???    IntentManager1.StartActivity('Open with?'); ---------------------------------------------------------------------- maurobio · 2023-06-07 20:22 Hi, @jmpessoa! I didn't understand this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i IntentManager1.StartActivity('Open with?'); Please be more specific. What exactly should be passed as parameter to StartActivity? Best regards, ---------------------------------------------------------------------- jmpessoa · 2023-06-07 20:42 QuoteOpen with? A simple message...... so, user can select the best appp [suggestion] to open the file...  If you will test it using "AppDownloagManageDemo1",  take care  of the URL and file mimetype   (as is, use "image/*") ---------------------------------------------------------------------- maurobio · 2023-06-07 21:06 Hi, @jmpessoa! OK, I will try it (with the AppDownloadManagerDemo1, for sure) and will post the results ASAP. Best regards, ---------------------------------------------------------------------- maurobio · 2023-06-07 22:00 Hi, @jmpessoa! I had yet no success in displaying the downloaded file. The download is successful and for pdf files the associated app is even called, but the document is not displayed. In the case of Excel files, a Java error message is raised. I attach the modified demo file. Please compile and run ii and take a look at the source to see if the mods I implemented (in jButton1Click event and jBroadcastReceiver1Receiver event) are correct. Thank you. Best regards, ---------------------------------------------------------------------- jmpessoa · 2023-06-07 23:18 sorry... FIXED!  --> GetFileUri(intent)  not   GetFileUri() Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   IntentManager1.SetAction(iaView);  IntentManager1.SetDataAndType(jDownloadManager1.GetFileUri(intent) , 'application/pdf');  //application/vnd.ms-excel ???  IntentManager1.StartActivity('Open with?'); ---------------------------------------------------------------------- maurobio · 2023-06-07 23:31 Hi, @jmpessoa! No error message this time - the file is downloaded, but, again, it is not opened and nothing happens... It is as if the StartActivity() method is never called. Best regards, ---------------------------------------------------------------------- jmpessoa · 2023-06-07 23:44 Here is my testd code: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {Hint: save all files to location: C:\adt32\eclipse\workspace\AppDownloadManagerDemo1\jni }unit unit1; {$mode delphi} interface uses  Classes, SysUtils, And_jni, And_jni_Bridge, Laz_And_Controls,  Laz_And_Controls_Events, AndroidWidget, downloadmanager, broadcastreceiver,  intentmanager; type   { TAndroidModule1 }   TAndroidModule1 = class(jForm)    ImageView1: jImageView;    IntentManager1: jIntentManager;    jBroadcastReceiver1: jBroadcastReceiver;    jButton1: jButton;    jCheckBox1: jCheckBox;    jDownloadManager1: jDownloadManager;    jTextView1: jTextView;    procedure AndroidModule1JNIPrompt(Sender: TObject);    procedure AndroidModule1RequestPermissionResult(Sender: TObject;      requestCode: integer; manifestPermission: string;      grantResult: TManifestPermissionResult);    procedure jBroadcastReceiver1Receiver(Sender: TObject; intent: jObject);    procedure jButton1Click(Sender: TObject);  private    {private declarations}  public    {public declarations}  end; var  AndroidModule1: TAndroidModule1; implementation {$R *.lfm}   { TAndroidModule1 } procedure TAndroidModule1.jButton1Click(Sender: TObject);var  res: TAndroidResult;begin     //hint: if you  get "write" permission then you have "read", too!   if not IsRuntimePermis sionGranted('android.permission.WRITE_EXTERNAL_STORAGE') then   begin     ShowMessage('Sorry... Some Runtime Permission NOT Granted ...');   Exit;   end;    if not Self.isConnected() then   begin     ShowMessage('Sorry,  Device is not connected...');     Exit;   end;   jBroadcastReceiver1.RegisterIntentActionFilter(jDownloadManager1.GetAc tionDownloadComplete()); //'android.intent.action.DOWNLOAD_COMPLETE'   jDownloadManager1.SaveToFile(dirDownloads, 'example12.pdf'); //http://clipart-library.com/images/6Tp5qzgnc.jpg  res:= jDownloadMana ger1.Start('https://od.lk/d/Ml8yMTQ3MzU1MDhf/example.pdf');   if res = RESULT_OK then    ShowMessage('OK!')  else    ShowMessage('FAIL'); end; procedure TAndroidModule1.jBroadcastReceiver1Receiver(Sender: TObject; intent: jObject);begin   (*  ShowMessage(jDownloadManager1.GetExtras(intent, '|'));  //MUST! be call first!   ShowMessage(jDownloadManager1.GetLocalFileName());  ShowMessage('Size(bytes): ' + IntToStr(jDownloadManager1.GetFileSizeBytes()) );  ShowMessage(jDownloadManager1.GetMediaType());  ShowMessage(jDownloadManager1.GetLocalUriAsString());                              //or Self.ParseUri(jDownloadManager1.GetLocalUriAsString())  jImageView1.SetImageFromURI( jDownloadManager1.GetFileUri() );  *)   //or   //jImageView1.SetImageFromURI( jDownloadManager1.GetFileUri(intent) );   //or  IntentManager1.SetAction(iaView);  IntentManager1.SetDataAndType(jDownloadManager1.GetFileUri(intent) , 'application/pdf');  //application/vnd.ms-excel ???  IntentManager1.StartActivity('Open with?'); end; procedure TAndroidModule1.AndroidModule1JNIPrompt(Sender: TObject);var  manifestPermissions: array of string;begin  if not Self.isConnected() then  begin //try wifi    if Self.SetWifiEnabled(True) then      jCheckBox1.Checked:= True    else      ShowMessage('Please,  try enable some connection...');  end  else  begin     if Self.isConnectedWifi() then jCheckBox1.Checked:= True  end;   if IsRuntimePermissionNeed() then   // that is, target API >= 23  - Android 6  begin     ShowMessage('RequestRuntimePermission....');      SetLength(manifestPermissions, 1);      //hint: if you  get "write" permission then you have "read", too!     manifestPermissions[0]:= 'android.permission.WRITE_EXTERNAL_STORAGE'; //from AndroodManifest.xml     Self.RequestRuntimePermission(manifestPermissions, 701);      SetLength(manifestPermissions, 0);  end;  end; procedure TAndroidModule1.AndroidModule1RequestPermissionResult(  Sender: TObject; requestCode: integer; manifestPermission: string;  grantResult: TManifestPermissionResult);begin  case requestCode of     701:begin              if grantResult = PERMISSION_GRANTED  then              ShowMessage('Success! ['+manifestPermission+'] Permission grant!!! ' )              else  //PERMISSION_DENIED                ShowMessage('Sorry... ['+manifestPermission+'] Permission not grant... ' );          end;  end;end; end. ---------------------------------------------------------------------- c4p · 2023-06-08 07:52 QuoteMy device has no such "Files and Media" option under Settings/Apps and Notifications/Permissions, but it has instead a "Memory" option which I checked to give permission. I am on Android 12, if you are on Android 10, you will see different options: Open Settings and navigate to Apps & notifications. From there, tap the Advanced option and then tap Permission Manager. You’ll see a list of all the various permissions on your device. Select your app to view the permissions, at least that's what it should be. Android 10 permissions have different categories. They are filed under Allowed or Denied. QuoteIt does not work for me. Result is the same: nothing happens, no error or warning message is issued. See permissions access in your Android 10 device, as above. QuoteUsing DownloadService instead of DownloadManager as before does not change anything. The file is correcelty downloaded, but still nothing happens - no warnings or error messages. Using jDownloadService was a suggestion to download direct to your project folder, jDownloadManager will not do this in it's current form AFAIK. I said this to get around the permissions issue but I think you said you want both options to work, so probably a moot point now. I would try and at least get one option working, then focus on getting the other one working, at least, that's what I would do. CopyFile will only work if you have permissions too, if you are wanting to copy from /Download to project folder 'Download', permissions are still required for the copy, same as open file. I don't know what your app actually does other than download a file from a website, presumably you want the user to have access to the downloaded file in /Download and open then permissions required. QuotePutting that code in the OnReceiver event does not changes anything. Again, not happens: no warnings, no error messages. This only works if you're using the jDownloadService and downloading direct to your Project 'Download' folder NOT from /Download. This was to workaround the permissions, but I think you said you want to resolve the permissions issue. It was a suggestion to at least getting a working prototype. ---------------------------------------------------------------------- maurobio · 2023-06-08 12:59 Hi, @BobDob! My problem is not to download the file, this I do without issues. My problem is to have it opened by the associated app once it is downloaded! Obviously, in such case a "console app" will not be useful. Regards, ---------------------------------------------------------------------- maurobio · 2023-06-08 13:01 Hi, @jmpessoa! Your tested code is identical to mine. It does not work. The file is downloaded, but it is not opened in the associated app as expected. Regards, ---------------------------------------------------------------------- maurobio · 2023-06-08 13:07 Hi, @c4p! QuoteI don't know what your app actually does other than download a file from a website, presumably you want the user to have access to the downloaded file in /Download and open then permissions required. My app is an extremely simple one: is just display a website where there are links to files in .xlsx and .pdf formats. What I want is simply have each file downloaded, when the link to that file is clicked, to any folder where it can be opened by the associated app!, Simple as that. But it is proving to be a nightmare.  I don't care if this is done using DownloadManager, DownloadService, or a magic wand - I just want that such a simple task, done by thousands of apps, work in my app! Best regards, ---------------------------------------------------------------------- maurobio · 2023-06-08 15:58 BobDog, We are dealing with ANDROID development, not "Windows". Thank you. ---------------------------------------------------------------------- maurobio · 2023-06-08 17:53 Hi, @BobDog! It is OK, sir! No need for apologies - I understand  you are willing to help! This vexing problem is rising the blood pressure of us all... Enjoy your tea (I love tea too). Best regards, ---------------------------------------------------------------------- c4p · 2023-06-08 20:48 Hey @maurobio This is my attempt, I have tweaked to so it 'should' just be a copy/paste into your unit1.pas file, apologies if I screwed anything up, the code should work, if you copy/paste to the current events, it works perfect for me, click file, downloads, and opens when complete with whatever mime type you assign, this uses your project folder 'Download' directory, have a look, make a backup first!....fingers crossed  Just standard permissions required for WRITE_EXTERNAL_STORAGE required which is already in your manifest file. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {hint: Pascal files location: ...\ReptileDatabase\jni }unit unit1; {$mode delphi} interface uses  {$IFDEF UNIX}{$IFDEF UseCThreads}  cthreads,  {$ENDIF}{$ENDIF}  Classes, SysUtils, StrUtils, AndroidWidget, menu, Laz_And_Controls, And_jni,  customdialog, broadcastreceiver, downloadmanager, intentmanager, downloadservice;  type   { TAndroidModule1 }   TAndroidModule1 = class(jForm)    jBroadcastReceiver1: jBroadcastReceiver;    jDownloadService1: jDownloadService;    jIntentManager1: jIntentManager;    jWebView1: jWebView;    jMenu1: jMenu;    jPanel1: jPanel;    jPanel2: jPanel;  jPanel3: jPanel;    jTextView2: jTextView;    jTextView3: jTextView;  jWebView1: jWebView;    Panel1: jPanel;    Panel2: jPanel;    TextView1: jTextView;    TextView2: jTextView;    TextView3: jTextView;    TextView4: jTextView;    TextView5: jTextView;    TextView6: jTextView;    TextView7: jTextView;    procedure AndroidModule1ClickOptionMenuItem(Sender: TObject;      jObjMenuItem: jObject; itemID: integer; itemCaption: string;      Checked: boolean);    procedure AndroidModule1CreateOptionMenu(Sender: TObject; jObjMenu: jObject);    procedure AndroidModule1Show(Sender: TObject);    procedure AndroidModule1SpecialKeyDown(Sender: TObject; keyChar: char;      keyCode: integer; keyCodeString: string; var mute: boolean);    procedure jBroadcastReceiver1Receiver(Sender: TObject; intent: jObject);    procedure jWebView1Status(Sender: TObject; Status: TWebViewStatus;      URL: String; var CanNavi: Boolean);  private    {private declarations}  public    {public declarations}  end; var  AndroidModule1: TAndroidModule1;  DownloadURL, URLFileName, Extension: string;  res: TAndroidResult; implementation  {$R *.lfm}   { TAndroidModule1 } procedure TAndroidModule1.jWebView1Status(Sender: TObject;  Status: TWebViewStatus; URL: String; var CanNavi: Boolean);var  SlashPos: integer;begin  //Pass the URL variable to our own variable to use in jDownloadReceiver later  DownloadURL := URL;  //Extract the file extension from the URL  Extension := ExtractFileExt(URL);  if (Extension = '.xlsx') or (Extension = '.xls') or (Extension = '.pdf') then   begin    //Get filename after the last slash in the URL using SlashPos position    SlashPos := LastDelimiter('/', URL); //Get the last occurrence of slash in the URL    //Get the actual filename so can use this later to save the file with the same name    URLFilename := AnsiRightStr(URL, Length(URL) - Slashpos);     //Let's delete the file if it exists in case we cache an old file, as we will need to download the latest version of the file    if fileexists(Self.GetEnvironmentDirectoryPath( dirDownloads)+'/'+URLFilename) then     begin       Self.DeleteFile(se lf.GetEnvironmentDirectoryPath(dirDownloads)+'/'+URLFilename);     end;       //Register Intent for download      jBroadcastReceiver1.Re gisterIntentActionFilter('org.lamw.AppShowDown.DOWNLOAD_RECEIVER'); //Register intent for Broadcast receiver      //What your downloaded file will be called, let's use the URL filename (there may be a method to get the filename?)      //Save file to project Download directory    jDownloadService1.SaveToFile(Self.GetEnvironmentDirectoryPath(dirDo wnloads), URLFIlename);      //Start the download      jDownloadService1.Start(URL, 'org.lamw.AppShowDown.DOWNLOAD_RECEIVER');      //Let user know we have started downloading      ShowMessage('Downloading file...please wait');   end;end; procedure TAndroidModule1.jBroadcastReceiver1Receiver(Sender: TObject;  intent: jObject);begin         //Store result code so we can check later if the download was successful         res := jBroadcastReceiver1.GetResultCode();         //Use res to check for successful download or fail         if (res = RESULT_OK) then        begin           ShowMessage('Download of' + sLineBreak + DownloadURL + sLineBreak + 'successful');           //Launch the file once it has downloaded            if (Extension = '.xls') then        // alternative office document mime type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'           begin              Self.StartDefaultActivityForFile(Self.GetE nvironmentDirectoryPath(dirDownloads) + '/'+ URLFIlename,'application/vnd.ms-excel'); //Start the downloaded file using Excel             end            else if (Extension = '.xlsx') then             begin              Self.StartDefaultActivityForFile(S elf.GetEnvironmentDirectoryPath(dirDownloads) + '/'+ URLFIlename,'application/vnd.ms-excel'); //Start the downloaded file using Excel             end            else if (Extension = '.pdf') then              begin               Self.StartDefaultActivityForFile (Self.GetEnvironmentDirectoryPath(dirDownloads) + '/'+ URLFIlename,'application/pdf'); //Start the downloaded file using PDF VIewer              end;           end             else if (res <> RESULT_OK) then              begin               ShowMessage('Download of' + sLineBreak + DownloadURL + sLineBreak + 'FAILED!');            end;    //unregister BroadcastReceiver ...   jBroadcastReceiver1.Unregister();end; procedure TAndroidModule1.AndroidModule1Show(Sender: TObject);begin    jWebView1.Navigate('http://biotupe.org/test/');end; procedure TAndroidModule1.AndroidModule1SpecialKeyDown(Sender: TObject;  keyChar: char; keyCode: integer; keyCodeString: string; var mute: boolean);begin    if (KeycodeString = 'KEYCODE_BACK') then  begin    if jWebView1.CanGoBack then      jWebView1.GoBack;    mute := True;  end;end; procedure TAndroidModule1.AndroidModule1CreateOptionMenu(Sender: TObject;  jObjMenu: jObject);var  i: integer;begin  for i := 0 to jMenu1.Options.Count - 1 do    jMenu1.AddItem(jObjMenu, i, jMenu1.Options.Strings[i], '',      mitDefault, misNever);end; procedure TAndroidModule1.AndroidModule1JNIPrompt(Sender: TObject);begin  jWebView1.SetLoadWithOverviewMode(True);  jWebView1.SetUseWideViewPort(True);end; procedure TAndroidModule1.AndroidModule1ClickOptionMenuItem(Sender: TObject;  jObjMenuItem: jObject; itemID: integer; itemCaption: string; Checked: boolean);begin  case itemID of    0:    begin      ShowMessage('The ShowDown App' + sLineBreak +        'This app demonstrates how to download and open' + sLineBreak +        'a linked file from a webpage with' + sLineBreak +        'the associated app' + sLineBreak + sLineBreak +        'This code does not belongs to anyone. Property is theft. Help yourself.',        gvCenter, slLong);    end;    1:      AndroidModule1.Close;  end;end; end. ---------------------------------------------------------------------- maurobio · 2023-06-08 21:16 Hi, @c4p! I got your message when I just finish another kind of test which presented some progress after more than a week of attempts: I got my app partially working on an old, cheap Hyundai "Maestro" tablet running Android 5.1.1! In this test, the app downloaded the file (this has never been a problem) and then correctly called the associated app (SmartOffice for xlsx, EBookDroid for pdf) but then each app complained that the file could not be opened. This was small progress, but at least I got evidence that the problem is really related to the version of Android running in the device. As an aside: I also tried my app in a most modern (and not so cheap) Samsung Tab 8.0 running Android 11.00. But this time I got an error from LAMW itself - it complained that "could not install apk" and so the app has not even been installed into the device. I will try your code with my personal device, which runs Android 10.0 and will report the results ASAP. Thank you very much! With warmest regards, ---------------------------------------------------------------------- maurobio · 2023-06-08 21:37 Hi, @c4p! When attempting to compile and install the modified app into the device, I got the following errors from LAMW: QuoteBuilding APK (Ant)... : Sucess Installing APK (Ant)... : Sucess Starting APK... : Sucess Starting: Intent { cmp=org.lamw.showdown/.App } Error type 3 Error: Activity class {org.lamw.showdown/org.lamw.showdown.App} does not exist. Of course, the app is not installed into the device. Any hints? Best regards, ---------------------------------------------------------------------- maurobio · 2023-06-08 21:56 Hi, @c4p! Don't worry about my previous message - there seem to be an inconsistency in the name speces of the AppShowDown. I added your code to my own app and this time it has been compiled and installed without any LAMW complaints. The app is installed and runs... the xlsx and pdf files are correctly downloaded... but then, as always, nothing happens! No associated app is called, no file is displayed. Maybe my (very simple) device running Android 10 simply cannot run this sort of app. I am at a loss and about to give up. Thanks a lot for your great efforts! With warmest regards, Best ---------------------------------------------------------------------- c4p · 2023-06-08 22:07 Hmmm check to see if the files exist in the path: Android/data/org.lamw.appname/files/Download if you have not already done this, if you find the files, try opening them directly on the device. See if that path exists on your device, you will need to have the device connected and in file transfer mode to get access if you cannot navigate to them on the device itself with a file manager. It could be that StartDefaultActivityForFile is not available on Android 10, I am using Android 12! I suspect we need another way to open the files directly using an intent, I think this may be on this thread somewhere, I will have a look. ---------------------------------------------------------------------- maurobio · 2023-06-08 22:25 Hi, @c4p! QuoteHmmm check to see if the files exist in the path: Android/data/org.lamw.appname/files/Download if you have not already done this, if you find the files, try opening them directly on the device. No such path exist in my system. QuoteSee if that path exists on your device, you will need to have the device connected and in file transfer mode to get access if you cannot navigate to them on the device itself with a file manager. I did not know this (that to see certain folders the device need to be connected). Anyway, even if connected, the path "Android/data/org.lamw.appname/files/Download " does not exist. The files downloaded by the app are put in the Downloads folder of the main storage. QuoteIt could be that StartDefaultActivityForFile is not available on Android 10, I am using Android 12! Maybe that is the case. But a solution in LAWM may do exist or eventually be found, because this can be done in Java: https://medium.com/@eliothijanoc/simple-way- to-download-and-read-files-on-android-api-28-3557e6d240e5 Many thanks! With warmest regards, ---------------------------------------------------------------------- c4p · 2023-06-09 07:44 Project folder might be in  /data/app/org.lamw.appname/files/Download  or /data/data/org.lamw.appname/files/Download on Android 10? ---------------------------------------------------------------------- maurobio · 2023-06-09 12:26 @Hi, c4p! QuoteProject folder might be in  /data/app/org.lamw.appname/files/Download  or /data/data/org.lamw.appname/files/Download on Android 10? There are no such folders in my device. If fact, I noticed that not only my app, but none of the LAMW demos have such folders. I also noticed that I have many apps installed in my device, but just a fraction of them create these strange and horrible domain-like names. Anyway, I few of them do have such folders, therefore they may be created in Android 10. ---------------------------------------------------------------------- c4p · 2023-06-09 16:34 I would suggest adding a button to your app and include the following code on the onclick event, this will tell you the path of where the files should be located: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i showmessage(self.GetEnvironmentDirectoryPath(dirDownloads)); ---------------------------------------------------------------------- maurobio · 2023-06-09 17:50 Hi, @c3p! The path displayed is: Quote/storage/emulated/0/Download Hope this helps. With warmest regards, ---------------------------------------------------------------------- c4p · 2023-06-09 19:49 Oh boy, that's why you've been having all the trouble, although the StartDefaultActivityForFile may still be an issue, totally worth trying this again. API differences for that environment variable between Android 10 & 12, on Android 10 (I honestly thought this would have changed in Android 10), dirDownloads means /Download, on Android 12 it means /Android/Data/org.lamw.appname/files/Download. I may be wide of the mark, but this seems to make sense now. The variable you 'probably' need is dirInternalAppStorage which probably goes to '/storage/emulated/0/data/user/0/org.lamw.appname' or '/data/user/0/org.lamw.appname' or something similar to that. This means every time you have been downloading it's been going to /Download. which you can't launch a file from there without manually changing the device permissions, at least that's what I think's been happening. Try the following code, you 'may' have to append +'/Download' to the dirInternalAppStorage environment variable, BUT (always a but) you will probably have to manually create the Download folder manually (it auto creates in Android 12 I think when you use dirDownloads) if it won't save to the root of the project dir, but I think it will (famous last words). What's changed is dirDownloads has been changed to dirInternalAppStorage, that's all, might be easier to do a find/replace in your code. If that does work, download and launches the files, you would have to check for Android versions <= Android 10 to use this environment and probably dirDownloads for > Android 10, anyone, one step at a time. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {hint: Pascal files location: ...\ReptileDatabase\jni }unit unit1; {$mode delphi} interface uses  {$IFDEF UNIX}{$IFDEF UseCThreads}  cthreads,  {$ENDIF}{$ENDIF}  Classes, SysUtils, StrUtils, AndroidWidget, menu, Laz_And_Controls, And_jni,  customdialog, broadcastreceiver, downloadmanager, intentmanager, downloadservice; type   { TAndroidModule1 }   TAndroidModule1 = class(jForm)    jBroadcastReceiver1: jBroadcastReceiver;    jDownloadService1: jDownloadService;    jIntentManager1: jIntentManager;    jWebView1: jWebView;    jMenu1: jMenu;    jPanel1: jPanel;    jPanel2: jPanel;  jPanel3: jPanel;    jTextView2: jTextView;    jTextView3: jTextView;  jWebView1: jWebView;    Panel1: jPanel;    Panel2: jPanel;    TextView1: jTextView;    TextView2: jTextView;    TextView3: jTextView;    TextView4: jTextView;    TextView5: jTextView;    TextView6: jTextView;    TextView7: jTextView;    procedure AndroidModule1ClickOptionMenuItem(Sender: TObject;      jObjMenuItem: jObject; itemID: integer; itemCaption: string;      Checked: boolean);    procedure AndroidModule1CreateOptionMenu(Sender: TObject; jObjMenu: jObject);    procedure AndroidModule1Show(Sender: TObject);    procedure AndroidModule1SpecialKeyDown(Sender: TObject; keyChar: char;      keyCode: integer; keyCodeString: string; var mute: boolean);    procedure jBroadcastReceiver1Receiver(Sender: TObject; intent: jObject);    procedure jWebView1Status(Sender: TObject; Status: TWebViewStatus;      URL: String; var CanNavi: Boolean);  private    {private declarations}  public    {public declarations}  end; var  AndroidModule1: TAndroidModule1;  DownloadURL, URLFileName, Extension: string;  res: TAndroidResult; implementation {$R *.lfm}  { TAndroidModule1 } procedure TAndroidModule1.jWebView1Status(Sender: TObject;  Status: TWebViewStatus; URL: String; var CanNavi: Boolean);var  SlashPos: integer;begin  //Pass the URL variable to our own variable to use in jDownloadReceiver later  DownloadURL := URL;  //Extract the file extension from the URL  Extension := ExtractFileExt(URL);  if (Extension = '.xlsx') or (Extension = '.xls') or (Extension = '.pdf') then   begin    //Get filename after the last slash in the URL using SlashPos position    SlashPos := LastDelimiter('/', URL); //Get the last occurrence of slash in the URL    //Get the actual filename so can use this later to save the file with the same name    URLFilename := AnsiRightStr(URL, Length(URL) - Slashpos);     //Let's delete the file if it exists in case we cache an old file, as we will need to download the latest version of the file    if fileexists(Self.GetEnvironmentDirectoryPath( dirInternalAppStorage)+'/'+URLFilename) then     begin       Self.Dele teFile(self.GetEnvironmentDirectoryPath(dirInternalAppStorage)+'/'+URL Filename);     end;       //Register Intent for download      jBroadca stReceiver1.RegisterIntentActionFilter('org.lamw.AppShowDown.DOWNLOAD_ RECEIVER'); //Register intent for Broadcast receiver      //What your downloaded file will be called, let's use the URL filename (there may be a method to get the filename?)      //Save file to project Download directory      jDownloadService1.SaveToFile(Self.GetEnvironmentDirecto ryPath(dirInternalAppStorage), URLFIlename);      //Start the download      jDownloadService1.Start(URL, 'org.lamw.AppShowDown.DOWNLOAD_RECEIVER');      //Let user know we have started downloading      ShowMessage('Downloading file...please wait');   end;end; procedure TAndroidModule1.jBroadcastReceiver1Receiver(Sender: TObject;  intent: jObject);begin         //Store result code so we can check later if the download was successful         res := jBroadcastReceiver1.GetResultCode();         //Use res to check for successful download or fail         if (res = RESULT_OK) then        begin           ShowMessage('Download of' + sLineBreak + DownloadURL + sLineBreak + 'successful');           //Launch the file once it has downloaded            if (Extension = '.xls') then        // alternative office document mime type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'           begin              Self.StartDefaultActivityForFile(Self.GetE nvironmentDirectoryPath(dirInternalAppStorage) + '/'+ URLFIlename,'application/vnd.ms-excel'); //Start the downloaded file using Excel             end            else if (Extension = '.xlsx') then             begin              Self.StartDefaultActivityForFile(S elf.GetEnvironmentDirectoryPath(dirInternalAppStorage) + '/'+ URLFIlename,'application/vnd.ms-excel'); //Start the downloaded file using Excel             end            else if (Extension = '.pdf') then              begin               Self.StartDefaultActivityForFile (Self.GetEnvironmentDirectoryPath(dirInternalAppStorage) + '/'+ URLFIlename,'application/pdf'); //Start the downloaded file using PDF VIewer              end;           end             else if (res <> RESULT_OK) then              begin               ShowMessage('Download of' + sLineBreak + DownloadURL + sLineBreak + 'FAILED!');            end;    //unregister BroadcastReceiver ...   jBroadcastReceiver1.Unregister();end; procedure TAndroidModule1.AndroidModule1Show(Sender: TObject);begin    jWebView1.Navigate('http://biotupe.org/test/');end; procedure TAndroidModule1.AndroidModule1SpecialKeyDown(Sender: TObject;  keyChar: char; keyCode: integer; keyCodeString: string; var mute: boolean);begin    if (KeycodeString = 'KEYCODE_BACK') then  begin    if jWebView1.CanGoBack then      jWebView1.GoBack;    mute := True;  end;end; procedure TAndroidModule1.AndroidModule1CreateOptionMenu(Sender: TObject;  jObjMenu: jObject);var  i: integer;begin  for i := 0 to jMenu1.Options.Count - 1 do    jMenu1.AddItem(jObjMenu, i, jMenu1.Options.Strings[i], '',      mitDefault, misNever);end; procedure TAndroidModule1.AndroidModule1JNIPrompt(Sender: TObject);begin  jWebView1.SetLoadWithOverviewMode(True);  jWebView1.SetUseWideViewPort(True);end; procedure TAndroidModule1.AndroidModule1ClickOptionMenuItem(Sender: TObject;  jObjMenuItem: jObject; itemID: integer; itemCaption: string; Checked: boolean);begin  case itemID of    0:    begin      ShowMessage('The ShowDown App' + sLineBreak +        'This app demonstrates how to download and open' + sLineBreak +        'a linked file from a webpage with' + sLineBreak +        'the associated app' + sLineBreak + sLineBreak +        'This code does not belongs to anyone. Property is theft. Help yourself.',        gvCenter, slLong);    end;    1:      AndroidModule1.Close;  end;end; end. ---------------------------------------------------------------------- maurobio · 2023-06-10 12:15 Hi, @c4p! I have bad news... The modified code did not work - in fact, it seems to be a step backward in comparison to a previous version which used the DownloadManager component instead of DownloadService, because now the file is not even downloaded! Shouldn't the directory '/data/user/0/org.lamw.appname/' exist? Or be created at a location in the file system which can be accessed by the app? Here are the values of dirDownloads and dirInternalAppStorage in my system: QuotedirDownloads = /storage/emulated/0/Download QuotedirInternalAppStorage = /data/user/0/org.lamw.appname/files (where appname is the name of my app) I suggest that we forgot about DownloadService and work with DownloadManager instead; also, we could use a fixed directory name instead of dirDownloads or dirInternalAppStorage or whatever Android throws at us, which should be created by the app beforehand (in case it does not already exist). May this be possible? With warmest regards, ---------------------------------------------------------------------- c4p · 2023-06-10 12:39 OK, hold up, I found an Android 10 phone, I will do some tests. ---------------------------------------------------------------------- maurobio · 2023-06-10 12:44 Hi, @c4p! I have not enough words in my poor pidgin English to thank you! But I can say with confidence that your heroic efforts will contribute to an initiative on biodiversity information outreach and, as a consequence, help our (the humankind, or the most rational fraction of it) efforts towards saving what is still possible... With warmest regards, ---------------------------------------------------------------------- maurobio · 2023-06-10 12:48 Hi, @c4p! I just tried this... Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i const  dirOutput = 'Android/data/user/0/org.lamw.appname/files '; (where appname is the name of my app) And then in the body of the procedure... Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i if not DirectoryExists(dirOutput) then CreateDir(dirOutput); Perhaps it is needless to say that this also did not work and no directory has been created. With warmest regards, ---------------------------------------------------------------------- c4p · 2023-06-10 13:49 I have had a play, downloaded file to project folder using the dirInternalAppStorage/Download path, but there is an issue launching an application using the intent (StartDefaultActivityForFile or JintentManager, can open browser fine, just not other apps, probably permissions), I will look into this more and get back to you, heading out right now, but will have a look when I get back. ---------------------------------------------------------------------- maurobio · 2023-06-10 13:57 Him @c4p! Thank you very much!!! With warmest regards, ---------------------------------------------------------------------- c4p · 2023-06-10 22:01 I can get it to open another app like Google Drive etc using the package name, but does not seem to want to use the file even with GetFileUri() via jDownloadManager, below code is just an example to launch another app, will launch Google Drive.....HasLaunchIntentForPackage was missing from previous examples, it will not open without this....did you ever get an app to launch using the app on Android 10 before? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     jIntentManager1.SetAction(iaView);    jIntentManager1.HasLaunchIntentF orPackage('com.google.android.apps.docs');    jIntentManager1.SetPackage('com.google.android.apps.docs');    jIntentManager1.StartActivity(); I did try via jDownloadManager/jBroacastReceiver method but still could not get to open the file. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     jIntentManager1.SetAction(iaView);    jIntentManager1.HasLaunchIntentF orPackage('com.google.android.apps.docs');    jIntentManager1.SetPackage('com.google.android.apps.docs');    jIntent Manager1.SetDataAndType(jDownloadManager1.GetFileUri(),'application/pd f');     jIntentManager1.StartActivity(); Fairly sure StartDefaultActivityForFile is not supported on Android 10 based on what I can see anyway, I suspect it's using Java code for Android 11+? This is an issue specific to Android 10, opening a file using StartDefaultActivityForFile works perfect for me in Android 12.....I don't think I can fix this on Android 10, weirdly, when I use the intent code above it doesn't work in Android 12, but StartDefaultActivityForFile does. Maybe @jmpessoa can help? ---------------------------------------------------------------------- maurobio · 2023-06-10 23:31 Hi, @c4p! I am sad about the bad news, but not surprised. Quotedid you ever get an app to launch using the app on Android 10 before? No, I did never attempted this before. QuoteFairly sure StartDefaultActivityForFile is not supported on Android 10 based on what I can see anyway It is what seems... But what to say of a web browser in the device being able to download and open a file?  For example, try the following on your mobile device (running either Android 10 or 12): Open the default browser and visit the address: http://biotupe.org/test/ Click on one of the linked files - in my device, the file is downloaded by the browser (to the main sotrage Downloads folder) and then opened in the associated app. In fact, this behaviour was just what I wanted to mimic in my app! QuoteMaybe @jmpessoa can help? Since he is the developer of LAMW, if he cannot help, who will? Unfortunately, he has been conspicuous by his absence. With warmest regards, ---------------------------------------------------------------------- c4p · 2023-06-11 12:06 jmpessoa should be able to help and is very knowledgeable, I'm confident he can fix this. ---------------------------------------------------------------------- maurobio · 2023-06-11 13:23 Hi, @cp4! I am surely confident he is working around the clock to solve this vexing problem, which anyway may seriously impair the more widespread use of LAMW. Best regards, ---------------------------------------------------------------------- jmpessoa · 2023-06-14 21:37 QuoteI am surely confident he is working around the clock.... No. File manipulation on android has become very complex... varying with each version and becoming more and more restrictive..... we need to be always studying and looking for new solutions (that meet different versions).... but for that we need a lot of free time... and now I don't have it.... due to the pressure of my professional activities.... ---------------------------------------------------------------------- maurobio · 2023-06-15 19:37 Hi, @jmpessoa! I cannot believe the problem is with this or that Android version, because I am using two devices with different versions (5.5.1 and 10) and in both I have problems with opening files. Therefore, the OS version cannot be the single issue at stake. Anyway, I will keep trying to solve the problem using LAMW. I have spent some time attempting to re-write the app with Delphi 11.3 to no avail! Even the most basic features which I already have in my LAMW app (as a beautiful overflowing menu) I could not implement in Delphi and FireMonkey! Not to mention that the Delphi IDE is ugly and confuse if compared to that of Lazarus IDE! In short, I firmly believe that LAMW is a great tool for developing Android apps in Object Pascal, much better in fact than Delphi & FireMonkey! Meanwhile, my app is already 99% complete and I will release at as it is. Users may have been able to download the files in Excel and PDF formats and open then with the proper apps in their devices, from the file manager. Best regards,