Recent

Author Topic: How to download a file from web page displayed by jWebView  (Read 6429 times)

maurobio

  • Hero Member
  • *****
  • Posts: 611
  • Ecology is everything.
    • GitHub
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,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

jmpessoa

  • Hero Member
  • *****
  • Posts: 2249
Re: How to download a file from web page displayed by jWebView
« Reply #1 on: May 27, 2023, 12:48:06 am »
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
Lamw: Lazarus Android Module Wizard
https://github.com/jmpessoa/lazandroidmodulewizard

maurobio

  • Hero Member
  • *****
  • Posts: 611
  • Ecology is everything.
    • GitHub
Re: How to download a file from web page displayed by jWebView
« Reply #2 on: May 27, 2023, 02:58:43 pm »
Hi, @jmpessoa!

I will take a look at the demos, they usually are always much useful.

Thanks a lot!

Best regards,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

maurobio

  • Hero Member
  • *****
  • Posts: 611
  • Ecology is everything.
    • GitHub
Re: How to download a file from web page displayed by jWebView
« Reply #3 on: May 31, 2023, 01:55:45 pm »
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,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

c4p

  • Full Member
  • ***
  • Posts: 133
Re: How to download a file from web page displayed by jWebView
« Reply #4 on: May 31, 2023, 08:28:09 pm »
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][+][-]
  1. 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?
« Last Edit: May 31, 2023, 08:47:48 pm by c4p »
Lazarus 2.0.12 r64642/FPC 3.2.0 on Windows 10 22H2, projects mainly built using AppCompat and Gradle v6.6.1.

maurobio

  • Hero Member
  • *****
  • Posts: 611
  • Ecology is everything.
    • GitHub
Re: How to download a file from web page displayed by jWebView
« Reply #5 on: May 31, 2023, 09:56:34 pm »
Hi, @c4p!

Thanks a lot for your clear and very comprehensive answer! It deserves a longer reply, as follows:

Quote
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.

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).

Quote
Quote
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 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!).

Quote
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:

I will try this ASAP!

Quote
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 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).

Quote
Quote
I 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,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

c4p

  • Full Member
  • ***
  • Posts: 133
Re: How to download a file from web page displayed by jWebView
« Reply #6 on: May 31, 2023, 10:09:56 pm »
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][+][-]
  1. WebView1.Navigate('https://getsamplefiles.com/sample-archive-files/zip');

Add to the 'OnStatus' event of WebView1.
Code: Pascal  [Select][+][-]
  1. procedure TTest.WebView1Status(Sender: TObject; Status: TWebViewStatus;
  2.   URL: String; var CanNavi: Boolean);
  3. var
  4.  res : TAndroidResult;
  5.  SlashPos : Integer;
  6.  URLFileName : String;
  7. begin
  8. if (containstext(URL, '.zip')) then //Can check in an array if you want with a bunch of extensions or another way?
  9.  begin
  10.   SlashPos := LastDelimiter('/', URL); //Get the last occurrence of slash in the URL
  11.   URLFilename := AnsiRightStr(URL, length(URL)-Slashpos); //Get filename after the last slash in the URL using SlashPos position
  12.   BroadcastReceiver1.RegisterIntentActionFilter(DownloadManager1.GetActionDownloadComplete()); //Register intent
  13.   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?)
  14.   res:= DownloadManager1.Start(URL); //Start the download
  15.  
  16.   //Use res to check for successful download or fail
  17.   if (res = RESULT_OK) then
  18.    begin
  19.     showmessage('Download successful');
  20.    end
  21.     else
  22.      showmessage('Download FAILED!');
  23.  end;
  24. 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][+][-]
  1. IntentManager1.SetAction('android.intent.action.VIEW');
  2. IntentManager1.SetMimeType('application/zip');
  3. IntentManager1.StartActivity();


More MIME types here: https://android.googlesource.com/platform/external/mime-support/+/9817b71a54a2ee8b691c1dfa937c0f9b16b3473c/mime.types
« Last Edit: May 31, 2023, 11:31:49 pm by c4p »
Lazarus 2.0.12 r64642/FPC 3.2.0 on Windows 10 22H2, projects mainly built using AppCompat and Gradle v6.6.1.

maurobio

  • Hero Member
  • *****
  • Posts: 611
  • Ecology is everything.
    • GitHub
Re: How to download a file from web page displayed by jWebView
« Reply #7 on: June 01, 2023, 09:27:02 pm »
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][+][-]
  1. procedure TAndroidModule1.jWebView1Status(Sender: TObject; Status: TWebViewStatus;
  2.   URL: string; var CanNavi: boolean);
  3. var
  4.   res: TAndroidResult;
  5.   SlashPos: integer;
  6.   URLFileName: string;
  7. begin
  8.   //ShowMessage(URL);
  9.   if (ContainsText(URL, '.xlsx')) then
  10.     //Can check in an array if you want with a bunch of extensions or another way?
  11.   begin
  12.     SlashPos := LastDelimiter('/', URL); //Get the last occurrence of slash in the URL
  13.     URLFilename := AnsiRightStr(URL, Length(URL) - Slashpos);
  14.     //Get filename after the last slash in the URL using SlashPos position
  15.     jBroadcastReceiver1.RegisterIntentActionFilter(
  16.       jDownloadManager1.GetActionDownloadComplete()); //Register intent
  17.     jDownloadManager1.SaveToFile(URLFIlename);
  18.     //What your downloaded file will be called, let's use the URL filename (there may be a method to get the filename?)
  19.     res := jDownloadManager1.Start(URL); //Start the download
  20.     //Use res to check for successful download or fail
  21.     if (res = RESULT_OK) then
  22.     begin
  23.       ShowMessage('Download of' + sLineBreak + URL + sLineBreak + 'successful');
  24.     end
  25.     else
  26.       ShowMessage('Download of' + sLineBreak + URL + sLineBreak + 'FAILED!');
  27.   end;
  28.  
  29.   //jIntentManager1.SetAction(iaView);  //or 'android.intent.action.VIEW'
  30.   jIntentManager1.SetAction('android.intent.action.VIEW');
  31.   jIntentManager1.SetMimeType('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
  32.   jIntentManager1.SetDataUri(jIntentManager1.ParseUri(URL)); // <-- This seems to be faulty!
  33.   jIntentManager1.StartActivity();
  34. end;
  35.  
  36.  

Any further hints?

Thanks a lot!

With warmest regards,

UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

c4p

  • Full Member
  • ***
  • Posts: 133
Re: How to download a file from web page displayed by jWebView
« Reply #8 on: June 03, 2023, 08:43:31 am »
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][+][-]
  1. IntentManager1.SetDataAndType('content://'+Self.GetEnvironmentDirectoryPath(dirSdCard) + '/Download/'+URLFileName,'application/vnd.ms-excel');

More info: https://forum.lazarus.freepascal.org/index.php/topic,46621.msg333891.html
« Last Edit: June 03, 2023, 09:01:52 am by c4p »
Lazarus 2.0.12 r64642/FPC 3.2.0 on Windows 10 22H2, projects mainly built using AppCompat and Gradle v6.6.1.

maurobio

  • Hero Member
  • *****
  • Posts: 611
  • Ecology is everything.
    • GitHub
Re: How to download a file from web page displayed by jWebView
« Reply #9 on: June 03, 2023, 04:07:49 pm »
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][+][-]
  1. jIntentManager1.SetDataAndType('content://' + Self.GetEnvironmentDirectoryPath(dirDownloads) + '/' + URLFilename, 'application/vnd.ms-excel');

and

Code: Pascal  [Select][+][-]
  1. 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,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

maurobio

  • Hero Member
  • *****
  • Posts: 611
  • Ecology is everything.
    • GitHub
Re: How to download a file from web page displayed by jWebView
« Reply #10 on: June 03, 2023, 08:32:29 pm »
Hi, @c4p!

Something like this do the trick in Java:

Code: Java  [Select][+][-]
  1. private void openFile(String file) {
  2. try {
  3.     Intent i = new Intent(Intent.ACTION_VIEW);
  4.     i.setDataAndType(Uri.fromFile(new File(file)), "application/pdf");//this is for pdf file. Use appropreate mime type
  5.     startActivity(i);
  6. } catch (Exception e) {          
  7.     Toast.makeText(this,"No pdf viewing application detected. File saved in download folder",Toast.LENGTH_SHORT).show();
  8. }
  9. }

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,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

jmpessoa

  • Hero Member
  • *****
  • Posts: 2249
Re: How to download a file from web page displayed by jWebView
« Reply #11 on: June 04, 2023, 01:44:30 am »
Quote
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.

LAMW:

i.SetDataAndType(i.ParseUri('file://'+_environmentDirectoryPath+'/'+ _fileName), "application/pdf")
« Last Edit: June 04, 2023, 01:49:10 am by jmpessoa »
Lamw: Lazarus Android Module Wizard
https://github.com/jmpessoa/lazandroidmodulewizard

maurobio

  • Hero Member
  • *****
  • Posts: 611
  • Ecology is everything.
    • GitHub
Re: How to download a file from web page displayed by jWebView
« Reply #12 on: June 04, 2023, 02:04:22 pm »
Hi, @jmpessoa!

Shouldn't it be:

Code: Pascal  [Select][+][-]
  1. 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,

UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

maurobio

  • Hero Member
  • *****
  • Posts: 611
  • Ecology is everything.
    • GitHub
Re: How to download a file from web page displayed by jWebView
« Reply #13 on: June 04, 2023, 04:01:27 pm »
Hi,

I really do fail to understand why something as simple as the code below does not work!

Code: Pascal  [Select][+][-]
  1. jIntentManager1.SetAction('android.intent.action.VIEW');
  2. jIntentManager1.SetDataAndType(jIntentManager1.ParseURI('file://' + Self.GetEnvironmentDirectoryPath(dirDownloads) + '/' + URLFilename), 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
  3. 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][+][-]
  1. ShowMessage('file://' + Self.GetEnvironmentDirectoryPath(dirDownloads) + '/' + URLFilename);

What is wrong?  >:(

Best regards,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

jmpessoa

  • Hero Member
  • *****
  • Posts: 2249
Re: How to download a file from web page displayed by jWebView
« Reply #14 on: June 04, 2023, 06:59:12 pm »
Test it for "application/pdf"  first!     


Otherwise,  You can try a direct jForm method:  (Test it for "application/pdf"  first , too!)     

Code: Pascal  [Select][+][-]
  1.    Self.StartDefaultActivityForFile(_filePath, _mimeType);
  2.  


but:
Quote
Android 11  - Api 30  (and up) has restricted developers to access devices folders (ex: "Download, Documents, ..., etc")"

the demo is here: "AppPublicFoldersAccessDemo1'
« Last Edit: June 04, 2023, 07:39:31 pm by jmpessoa »
Lamw: Lazarus Android Module Wizard
https://github.com/jmpessoa/lazandroidmodulewizard

 

TinyPortal © 2005-2018