B4A Library WebViewAssetLoader - the demo

here is a demonstration of the WebViewAssetLoader class API.

questions about webview's failing to load local resources under sdk30 are starting to pop up occasionally. they are, of course, beaten down by a chorus of "don't use webview!" i'm not here to judge.

what it boils down to is google wants you to use the https:// scheme to load local resources into webviews. this is a problem if you don't run a secure server on the same device as the app.

to allow you to use the https:// scheme, google has created a dummy secure url. with the webviewassetloader api, you keep your local files in dirassets or dirinternal, like always, but load them using the dummy url instead of the file:// scheme, which is what google is turning off. (yes, i know it's possible to turn it on - for the moment - and i am also aware of a number of other considerations and questions, but for the purposes of the demo, i'm haven't addressed them here. i previously referred to some workarounds in this post. i have no doubt they will be phased out once everyone is onboard with the assetloader.)

to run the demo, you need to:
1) unzip the attached archive.
2) copy/move the .jar and .xml files to your additional libraries folder.
3) open your sdk manager and look for "webkit". you're looking for "androidx.webkit:webkit (Google Maven) Version 1.4.0". download it, if applicable. this is the assetloader api.
4) build and run the demo. (b4a11, sdk30, right?)

if you are among those encountering the net::ERR_ACCESS_DENIED problem as a result of trying to load a webview with file://, the demo should work for you. if you look closely at my test file, you will see how you can even load local resources from within the test file. (and if you keep sub-folders in dirinternal, you can load from them as well. i didn't do that for the demo.)

if the demo doesn't run correctly, and you've run it on a recent device targeting sdk30, i'll try to help. i've tested it on 2 devices running android 11, targeting sdk30 and built with b4a 11.

the api overrides aspects of the webviewwrapper in our b4a core library. and it overrides some aspects of android's own webview, so i would assume that will change as google catches up with what may be unintended behavior and people start complaining loud enough. for the moment, google seems intent on shutting down vulnerabilities first.
 

Attachments

  • webviewload.zip
    48.3 KB · Views: 56

Javier Alonso

Member
Licensed User
Great, drgottjr! This is precisely what I have been looking for.

I have a couple of questions. First, I host the page in File.DirInternal, not the assets folder. How do I access that folder? (maybe https://appassets.androidplatform.net/files/atest.html?)
Second, I am using WebViewExtras to inject and execute some javascript in the pages. Will it work after adding the gassetsloader library?

Thanks in advance!
 

drgottjr

Well-Known Member
Licensed User
sorry, i realized i should have included the dummy url for file.dirinternal after i uploaded the library.
here's the url:
B4X:
        ' if your files are in dirinternal, use this:
        ' webview.LoadUrl("https://appassets.androidplatform.net/public_data/atest.html")

        ' if your files are in 1 or more sub-folders in dirinternal, just add the sub-folder to the base url.
        ' eg, if your images are kept in dirinternal/images, load them like this:
        ' webview.LoadUrl("https://appassets.androidplatform.net/public_data/images/animage.jpg")

it's already supported in the library, so no change there. why google chose "public_data" as the name for a folder which clearly isn't public, i can't say. they're all billionaires, so they must be doing something right.

and, for whatever reason, the last time i looked, there was no dummy secure url for what we call "safe" direxternal. you would think after doing everything it could to make us use such a location, google would have included it in the assetloader api. i'll check again.

if you had nothing better to do, you might try sticking a file in safedirexternal and see if the assetloader finds it when you use the dummy secure url for file.dirinternal. i'll probably try myself; you're the first one who's shown any interest.

as i think i mentioned early on, there are some issues with this api. they may never affect your app. feel report to report back any bizarre behavior. my hope was that google will ultimately see them and update the api. the loader part does what it says it does. but the api overrides some of webview's and its affiliates' behavior. no sense in getting into it all now.

as for javascript injection, i added webviewextras to the b4a example and set the javascript interface. in the pagefinished sub, i added a simple alert in the example:

B4X:
' in create:
dim webviewextras as webviewextras
webviewextras.addWebChromeClient(webview, "cc")
webviewextras.addJavascriptInterface(webview, "B4A")

webviewextras.addWebChromeClient     <--- NO NO NO NO NO NO NO  THIS CONFLICTS WITH THE ASSET LOADER (and vice versa)

later:
Sub gal_PageFinished (Url As String)
    Log("finished loading: " & Url)
    dim javascript as string = "javascript:alert('hello from the webviewassetloader');"
    webviewextras.executejavascript( webview, javascript )
End Sub

it worked fine, so javascript injection seems to be ok. NOTE: DO NOT ADD webviewclient IN WEBVIEWEXTRAS. webviewextras and the webviewassetloader will nullify each other in this respect. i added webviewextras chomeclient, apparently without incident.
 
Last edited:

Javier Alonso

Member
Licensed User
Thank you, drgottjr! I managed to set it up following your instructions. I am using you library together with informatix's Webreader (actually a webview with a handful of interesting properties to read epubs) and there is only one thing missing: I should need to expose the webviewclient->shouldOverrideUrlLoading event in the gal library, because putting both libraries together, the event in the Webreader library is not working.

Would it be possible that you include this event in your library? I need to catch the event of the user clicking on a link inside the ebook...

Thanks in advance. I promise to start learning pure java asap ;-)
 

drgottjr

Well-Known Member
Licensed User
i'm not familiar with webreader. looks like there is a conflict between it and the assetloader library. it depends on what webreader does. if it sets its own webviewclient, it will kill mine. and vice versa (it depends on which library you add last. that's the library which prevails.)

**************************THIS SUPERCEDES THE REPLY THAT USED TO BE HERE. **************************
shouldoverrideurlloading() works. it defaults to false, which means the requested page loads. if you have the overrideurl sub set up in your b4a project, you can control whether or not the requested page loads. i went through version 0.02 again and did a number of tests relating to shouldoverride. in any case,
i've attached an update.

if you had the misfortune to read my earlier post (and which i am now basically overwriting), i apologize.

there is still the main issue of conflict between webview-related libraries. a webview can only have 1 webviewclient. if you load a couple webview-related libraries which happen to set their own webviewclient, the last library to load is the one that gets the webviewclient. the other libraries are effectively nullified, at least as far as webviewclient methods are concerned. if some feature you used no longer works (and you want to bring it to my attention),
i need to see code you used to add any webview-releated libraries to the app.

another edit:
i took a longer look at webreader. it extends our standard webview (wrapper), which has its own webviewclient (for methods like overruleurl), so the situation is as i've explained: only 1 webviewclient per webview. the others don't support the assetloader api; mine does. whichever library you load last gets the webviewclient.
 

Attachments

  • gassetloader.zip
    6.6 KB · Views: 22
Last edited:
Top