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,