save webview html file

mkvidyashankar

Active Member
Licensed User
Longtime User
Error in saving html file

B4X:
Sub Process_Globals
Dim hc As HttpClient
Dim req As HttpRequest
End Sub

Sub Globals
   'These global variables will be redeclared each time the activity is created.
   'These variables can only be accessed from this module.
   Dim WebView1 As WebView
   
End Sub

Sub Activity_Create(FirstTime As Boolean)
   Activity.LoadLayout("layoutMain")
   '   add the B4A javascript namespace to the WebView
   'WebInterface.addJSInterface(WebView1, "B4A")
   '   now load a web page
   WebView1.LoadUrl("http://www.b4x.com/")
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub

Sub WebView1_PageFinished (Url As String)
   getremotemessages("http://www.b4x.com/")
End Sub

Sub GetRemoteMessages(postUrl As String)               
   'Set up an http request connection
     req.InitializeGet(PostUrl)
   hc.Execute(req, 1)                                                
End Sub

Sub hc_ResponseSuccess (Response As HttpResponse, TaskId As Int)         'We got connection and data !!

    Dim resultString As String
    resultString = Response.GetString("UTF8")   'This holds the returned data 
    WebView1.LoadHtml(resultString)
   response.Release
   File.WriteList(File.DirDefaultExternal,"trial.html",resultstring)         
            
End Sub
Sub hc_ResponseError (Response As HttpResponse, Reason As String, StatusCode As Int, TaskId As Int)      'No connection :-(
    Log("Error connecting: " & Reason & " " & StatusCode)
    If Response <> Null Then
        Log(Response.GetString("UTF8"))
      ProgressDialogHide
        Response.Release
    End If
End Sub

I tried your code with save option, but not able to retrieve and save, please help:sign0085:
 
Upvote 0

knarf123

New Member
Licensed User
Longtime User
error when executing scripts

Here's an alternative that should do as the OP originally asked.

First you need to use my JSInterface library.
Now you can execute javascript in your WebView from your B4A code and your WebView can also now call a B4A Sub.

B4X:
'Activity module
Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.

End Sub

Sub Globals
   'These global variables will be redeclared each time the activity is created.
   'These variables can only be accessed from this module.
   
   Dim myInterface As JSInterface
   Dim WebView1 As WebView
End Sub

Sub Activity_Create(FirstTime As Boolean)
   Activity.LoadLayout("layoutMain")
   WebView1.Width=100%x
   WebView1.Height=100%y
   
   '   add the B4A javascript interface to the WebView
   myInterface.addJSInterface(WebView1, "B4A")
   
   '   now load a web page
   WebView1.LoadUrl("http://www.b4x.com/android/help/jsinterface.html")
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub WebView1_PageFinished (Url As String)
   '   Now that the web page has loaded we can get the page content as a String
   Dim jsStatement As String
   
   jsStatement="B4A.CallSub('processHTML', document.documentElement.outerHTML)"
   
   Log("PageFinished: "&jsStatement)
   myInterface.execJS(WebView1, jsStatement)
End Sub

Sub processHTML(html As String)
   '   This is the Sub that we'll get the web page to send it's HTML content to
   
   '   Log may truncate a large page so you'll not see all of the HTML in the log but the 'html' String should still contain all of the web page HTML
   
   Log("processHTML: "&html)
End Sub

You can see that the code waits for the PageFinished event before requesting that the web page sends it's HTML content to the B4A Sub 'processHTML'.

This method has an advantage over the previously posted examples - that is when a web page had been dynamically created and it's content is not static.
The user may have submitted a form for example and be viewing a (dynamically generated) web page that cannot be requested using HttpClient.

Martin.

Martin,
I tried your example but I am getting the following error:
"Compiling code. Error
Error parsing program.
Error description: Unknown type: jsinterface
Are you missing a library reference?
Occurred on line: 12
Dim myInterface As JSInterface"

I added the reference files to C:\Basic4android\Libraries


Do I also need to add it in B4A?
I am new to B4.
Regards,
Frank
 
Upvote 0

peacemaker

Expert
Licensed User
Longtime User
I use 5 pcs of WebViews, all of them set as:
WvE(i).addJavascriptInterface(wv(i), "B4A")

After:
jsStatement="B4A.CallSub('processHTML', document.documentElement.outerHTML)"
WvE(i).executeJavascript(wv(i), jsStatement)

the application is silently closed :-((((
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
The syntax you are using in your CallSub statement is the syntax for my older JSInterface library.

The newer WebViewExtras requires an extra parameter callUIThread:

CallSub(subName As String, callUIThread As boolean, parameter1 As String)

The callUIThread parameter is an important update - it's not available with JSInterface.

Does the Sub called by your javascript modify your activity UI?
If the answer is yes then you need to pass boolean true as callUIThread otherwise you can pass false.
If you pass false and then the Sub tries to modify your activity UI you will get an exception.

So you need to modify your code to:

B4X:
Dim callUIThread As Boolean
callUIThread=??
jsStatement="B4A.CallSub('processHTML', callUIThread, document.documentElement.outerHTML)"
WvE(i).executeJavascript(wv(i), jsStatement)

Choosing a value for callUIThread based on whether the javascript causes your B4A activity to make any changes to the user interface.

Generally, if the javascript is not going to receive a return value from B4A you can use True even if the UI is not modified.

Martin.
 
Upvote 0

peacemaker

Expert
Licensed User
Longtime User
No help, with True or False.
with
jsStatement="B4A.CallSub('processHTML', True\False, document.documentElement.outerHTML)" - also
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
Oops...!


The javascript statement String should be:

B4X:
"B4A.CallSub('processHTML', true, document.documentElement.outerHTML)"

OR

B4X:
"B4A.CallSub('processHTML', false, document.documentElement.outerHTML)"

Javascript uses all lower case for true and false.

If that still fails then add the WebChromeClient to your WebView and look at the Log for any relevant error messages:

B4X:
MyWebViewExtras.addWebChromeClient(WvE(i))

If your app force closes then look at the unfiltered Log for errors.

Martin.
 
Upvote 0

peacemaker

Expert
Licensed User
Longtime User
Strange, but does not help. Adding WebChromeClient also.

B4X:
Sub SaveHTML (i As Int)
    '    Now that the web page has loaded we can get the page content as a String
    Dim jsStatement As String
    jsStatement="B4A.CallSub('processHTML', false, document.documentElement.outerHTML)"
    
    WvE(i).executeJavascript(wv(i), jsStatement)
End Sub

Sub processHTML(html As String) As String
   
    Log("processHTML: "&html)
   Return html
End Sub
 

Attachments

  • log.txt
    7.8 KB · Views: 367
Upvote 0

warwound

Expert
Licensed User
Longtime User
First thing i see in your log is a problem with the WebViewXtended library:

Could not find method android.webkit.WebView.canZoomIn, referenced from method thalmy.webviewxtended.xtender.canZoomIn
VFY: unable to resolve virtual method 412: Landroid/webkit/WebView;.canZoomIn ()Z
VFY: replacing opcode 0x6e at 0x0000
VFY: dead code 0x0003-0008 in Lthalmy/webviewxtended/xtender;.canZoomIn (Landroid/webkit/WebView;)Ljava/lang/Boolean;
Could not find method android.webkit.WebView.canZoomOut, referenced from method thalmy.webviewxtended.xtender.canZoomOut
VFY: unable to resolve virtual method 413: Landroid/webkit/WebView;.canZoomOut ()Z
VFY: replacing opcode 0x6e at 0x0000
VFY: dead code 0x0003-0008 in Lthalmy/webviewxtended/xtender;.canZoomOut (Landroid/webkit/WebView;)Ljava/lang/Boolean;

The parts of the log that look to be WebViewExtras related make no sense to me:

JNI WARNING: jarray 0x40580f90 points to non-array object (Ljava/lang/String;)
"WebViewCoreThread" prio=5 tid=11 NATIVE
| group="main" sCount=0 dsCount=0 obj=0x40583d68 self=0x267ab8
| sysTid=12760 nice=0 sched=0/0 cgrp=default handle=2523448
| schedstat=( 509754101 354504239 113 )
at android.webkit.BrowserFrame.stringByEvaluatingJavaScriptFromString(Native Method)
at android.webkit.BrowserFrame.stringByEvaluatingJavaScriptFromString(Native Method)
at android.webkit.BrowserFrame.loadUrl(BrowserFrame.java:246)
at android.webkit.WebViewCore.loadUrl(WebViewCore.java:1570)
at android.webkit.WebViewCore.access$1400(WebViewCore.java:53)
at android.webkit.WebViewCore$EventHub$1.handleMessage(WebViewCore.java:956)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.webkit.WebViewCore$WebCoreThread.run(WebViewCore.java:629)
at java.lang.Thread.run(Thread.java:1019)


Yet a Google for jarray points to non-array object took me to this thread at StackOverflow:

This is a bug with 2.3.x. simulator - Javascript->Java bridge is bugged.

The Google bug specifically uses this demo code. Issue 12987 - android - Javascript to Java Bridge Throws Exception on Android 2.3 - Android - An Open Handset Alliance Project - Google Project Hosting

Go star it so they know to fix it soon.

You can workaround this for now by just using a 2.2 emulator.

Are you running your code on a 2.3 emulator?

Martin.
 
Upvote 0

peacemaker

Expert
Licensed User
Longtime User
Are you running your code on a 2.3 emulator?
Martin.

EXACTLY ! 2.2 emulator works OK !
Thank you very much !
And update the first post with the lib to warn users about this emulator problem, pls.
 
Last edited:
Upvote 0

zeuspower

Member
Licensed User
Longtime User
hello from Greece,to all the team here and a big BRAVO to the makers of
B4a !!!

My problem is this:

I want to save the contents of a webview to a string
(i can't use http methods,because the page is not directly accessible,it
needs javascripts to go to the page i want...)

so i make some "games" with the pageFinished and some javascripts
and i go to the desired page but i can't get it as string..

to get the page to a string, i use the following :

B4X:
Dim jsStatement

             jsStatement="B4A.CallSub('processHTML',true, document.documentElement.outerHTML)"

MyWebViewExtras.executeJavascript(WebView1,jsStatement)

---------------
Sub processHTML(html As String)

   Log("processHTML: " & html)
   
   End Sub


it did nothing,until i used the addwebchromeclient method and i discovered
at the log the following error:


ReferenceError: Can't find variable: B4A in undefined (Line: 1)

oh,I forgot,i tried it on both 2.2 and 2.3 emulators...
 
Last edited:
Upvote 0

warwound

Expert
Licensed User
Longtime User
ReferenceError: Can't find variable: B4A in undefined (Line: 1)

B4A is undefined - you try to execute the javascript B4A.CallSub('processHTML',true, document.documentElement.outerHTML) which causes this error.

Sounds to me as though you have either not used WebViewExtras to add a JavascriptInterface OR you have not used 'B4A' as the interface name.

B4X:
MyWebViewExtras.addJavascriptInterface(WebView1, "B4A")

That will add the JavascriptInterface with the "B4A" interface name and now you should be able to execute B4A.CallSub('processHTML',true, document.documentElement.outerHTML).

Martin.
 
Upvote 0

Gregg Homan

Member
Licensed User
Longtime User
Hello,

WarWound wrote example code (see below) on 7/11/2011 that demonstrated how to use his library WebViewExtras to save html content via WebView. I am using B4A V3.20 and WebViewExtras V1.40 and I saw no forum posts that suggest that this code fails yet when I execute this example code it fails and I get the following error showing up in the log:

Ignoring event: processhtml. Raised from the wrong thread.

Can anyone suggest what is causing the example code below (per WarWound) to fail?

Thanks,
Gregg

B4X:
'Activity module
Sub Process_Globals
End Sub

Sub Globals
    Dim myInterface As WebViewExtras 'Requires WebViewExtras library which replaced JSInterface Library
    Dim WebView1 As WebView
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("layoutMain")
    myInterface.addJavascriptInterface(WebView1, "B4A")
    WebView1.LoadUrl("http://www.b4x.com/android/help/jsinterface.html")
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub

Sub WebView1_PageFinished (Url As String)
    Dim jsStatement As String = "B4A.CallSub('processHTML', document.documentElement.outerHTML)"
    myInterface.executeJavascript(WebView1, jsStatement)
End Sub

Sub processHTML(html As String)
    Log("processHTML: "&html)
End Sub
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
Upvote 0
Top