1. *** New version of B4J is available ***
    B4J v7.8
    Dismiss Notice

Android Question Catching error messages from Webview using WebviewExtras

Discussion in 'Android Questions' started by CidTek, Oct 10, 2013.

  1. CidTek

    CidTek Active Member Licensed User

    I'm loading html into a WebView that is Google Maps V3 JS (loads a map with markers) and I need to know if an error occurs so I can reload the WebView.

    I've seen several references to WebviewExtras console logs but no clear example on how they used.
     
  2. warwound

    warwound Expert Licensed User

    You need to add a WebChromeClient to your WebView, you'll now see all console messages from the WebView in the android log.

    Take a look at this example:

    Code:
    Sub Process_Globals

    End Sub

    Sub Globals
       
    Dim WebView1 As WebView
       
    Dim WebViewExtras1 As WebViewExtras
    End Sub

    Sub Activity_Create(FirstTime As Boolean)
       WebView1.Initialize(
    "WebView1")
       WebViewExtras1.addWebChromeClient(WebView1, 
    "")
       
    Activity.AddView(WebView1, 0,0100%x100%y)
       WebView1.LoadUrl(
    "http://www.basic4ppc.com/android/forum/threads/catching-error-messages-from-webview-using-webviewextras.33437/#content")
    End Sub

    Sub Activity_Resume

    End Sub

    Sub Activity_Pause (UserClosed As Boolean)

    End Sub

    Sub WebView1_PageFinished (Url As String)
       
    Dim Javascript As String="alertt('Hello World');"
       WebViewExtras1.executeJavascript(WebView1, Javascript)
    End Sub
    The log shows:

    Not only is my deliberate javascript error reported (i used alertt instead of alert) but also some other errors.
    If you are writing your own webpages you can make use of this using javascript such as:

    Code:
    console.log('Hello World');
    Martin.
     

    Attached Files:

    eps and Erel like this.
  3. CidTek

    CidTek Active Member Licensed User

    Hi Martin,

    How can you detect the presence of errors from within the app itself in real time? My situation (blank webview) is not handled by sitting at a PC looking the log in the IDE but it can be fixed by refreshing the Webview if the presence of an error is detected.
     
  4. warwound

    warwound Expert Licensed User

    Hi again.

    Take a look at the library code which sends the WebView console messages to the android log:

    Code:
    public boolean onConsoleMessage(final ConsoleMessage consoleMessage1) {
             
    String logMessage = consoleMessage1.message() + " in " + consoleMessage1.sourceId() + " (Line: " + consoleMessage1.lineNumber() + ")";
             BA.Log(logMessage);
             
    return true;
           
    }
    The WebChromeClient onConsoleMessage callback is passed a ConsoleMessage object, it strips the error message, source and line number from the ConsoleMessage and logs those values.

    I could put a custom WebChromeClient together which instead of logging the console messages raises a b4a event and passes either the ConsoleMessage object or the error message, source and line number.
    Ie the event could receive a ConsoleMessage and you could access the ConsoleMessage methods/properties, or the library could could extract the error message, source and line number from the ConsoleMessage and pass those values instead of the ConsoleMessage object.

    Would that be of any use in your project?
    To be honest i think that's about the best (only) solution available.

    Martin.
     
  5. warwound

    warwound Expert Licensed User

    I decided it'd be a good update to raise an event and pass the ConsoleMessage object to b4a rather than logging the console message values to the android log.

    So i've updated WebViewExtras2, which is the not yet officially uploaded updated version of WebViewExtras.
    Grab the latest version of WebViewExtras2 from here: http://android.martinpearman.co.uk/b4a/temp/WebViewExtras2_20131012.zip.

    Here's a sample project:

    Code:
    Sub Process_Globals

    End Sub

    Sub Globals
       
    Dim WebViewExtras1 As WebViewExtras
    End Sub

    Sub Activity_Create(FirstTime As Boolean)
       
    Dim WebView1 As WebView
       WebView1.Initialize(
    "")
       WebViewExtras1.Initialize(WebView1)
       
       
    Dim WebChromeClient1 As DefaultWebChromeClient
       WebChromeClient1.Initialize(
    "WebChromeClient1")
       
       WebViewExtras1.SetWebChromeClient(WebChromeClient1)
       
       
    Activity.AddView(WebViewExtras1, 00100%x100%y)
       
       WebViewExtras1.LoadUrl(
    "http://www.basic4ppc.com/android/forum/threads/catching-error-messages-from-webview-using-webviewextras.33437/#post-195766")
    End Sub

    Sub Activity_Resume

    End Sub

    Sub Activity_Pause (UserClosed As Boolean)

    End Sub

    Sub WebChromeClient1_ConsoleMessage(ConsoleMessage1 As ConsoleMessage) As Boolean
       
    Dim Message As StringBuilder
       
       Message.Initialize
       Message.Append(
    "WebChromeClient1_ConsoleMessage: ")
       
    Select ConsoleMessage1.MessageLevel
         
    Case ConsoleMessage1.DEBUG
           Message.Append(
    "DEBUG")
         
    Case ConsoleMessage1.ERROR
           Message.Append(
    "ERROR")
         
    Case ConsoleMessage1.Log   '   the compiler insists on changing LOG to Log!
           Message.Append("LOG")
         
    Case ConsoleMessage1.TIP
           Message.Append(
    "TIP")
         
    Case ConsoleMessage1.WARNING
           Message.Append(
    "WARNING")
       
    End Select
       
    Log(Message.ToString)
       
       Message.Initialize
       Message.Append(ConsoleMessage1.Message)
       Message.Append(
    " in ")
       Message.Append(ConsoleMessage1.SourceId)
       Message.Append(
    " (Line: ")
       Message.Append(ConsoleMessage1.LineNumber)
       Message.Append(
    ")")
       
       
    Log(Message.ToString)
       
       
    Return True
    End Sub
    You'll see the syntax for WebViewExtras2 is completely different to WebViewExtras.
    WebViewExtras was a bunch of static methods that you passed an instance of a WebView to in order to execute a method.
    WebViewExtras2 is a 'proper' instance of a WebView.

    This is the new ConsoleMessage object reference:

    ConsoleMessage
    Fields:

    • DEBUG As MessageLevel
    • ERROR As MessageLevel
    • LOG As MessageLevel
    • TIP As MessageLevel
    • WARNING As MessageLevel
    Methods:
    • IsInitialized As Boolean
    • LineNumber As Int
    • Message As String
    • MessageLevel As MessageLevel
    • SourceId As String

    Don't try to use both WebViewExtras and WebViewExtras2 in the same b4a project, WebViewExtras2 can do all that WebViewExtras can do and a lot more.
    If you need help converting from WebViewExtras to WebViewExtras2 then let me know.

    The sample project is attached.

    Martin.
     

    Attached Files:

  6. CidTek

    CidTek Active Member Licensed User

    Brilliant!!!

    That fixed my issue which I guess I should explain. I ported my transit app to run on Blackberry OS10 whose versions vary from 10.0 and the soon to be released 10.2. The older versions of BB10 don't always play nice with Google maps V3 javascript in a Webview and require a refresh of the Webview until the map and markers display. This can vary from 0 to 3 refreshes depending on it's mood I guess.

    The error was "Uncaught TypeError: Cannot read property 'style' of undefined in file/// (line 25)"

    Now when I detect a console error I just...
    WebView1.StopLoading
    WebView1.LoadHtml(HTML)

    which seems to work so smooth the user can't tell there was an issue.

    This will be less of an issue as BB10.2 is released.

    Thanks so much for this solution and I sent you a contribution in appreciation.
     
    Last edited: Oct 13, 2013
  7. CidTek

    CidTek Active Member Licensed User

    What is the syntax for adding an interface name with the new library (WebViewExtras2)?

    I'm getting "Uncaught ReferenceError: B4A is not defined" when I use the following js.

    google.maps.event.addListener(map, 'click', function(event) {
    latLon = event.latLng.lat().toFixed(6) + ' |' + event.latLng.lng().toFixed(6);
    B4A.CallSub('ShowToast', true, latLon);
    });
     
  8. warwound

    warwound Expert Licensed User

    The B4A object your error refers to is the InterfaceName passed to the WebViewExtras AddJavascriptInterface method:

    AddJavascriptInterface (JavascriptInterface As Object, InterfaceName As String)
    Injects the supplied Java object into this WebView.
    JavascriptInterface - The Java object to inject into this WebView's JavaScript context. Null values are ignored.
    InterfaceName - The name used to expose the object in JavaScript.

    Most of my examples use B4A as the InterfaceName but you can use just about any name you want.

    Martin.
     
  9. CidTek

    CidTek Active Member Licensed User

    Note I am using WebViewExtras2

    I added the javascript interface

    WebviewExtras1.Initialize(WebView1)
    Dim WebChromeClient1 AsDefaultWebChromeClient
    WebChromeClient1.Initialize("WebChromeClient1")
    WebviewExtras1.SetWebChromeClient(WebChromeClient1)
    WebviewExtras1.addJavascriptInterface(WebView1, "B4A")


    I get this error...
    Uncaught TypeError: Object android.webkit.WebView@414e1de0 has no method 'CallSub'

    with this code...

    google.maps.event.addListener(map, 'click', function(event) {
    var LatLon = event.latLng.lat().toFixed(6) + ' |' + event.latLng.lng().toFixed(6);
    B4A.CallSub('ShowToast', true, LatLon);
    });
     
    Last edited: Oct 22, 2013
  10. warwound

    warwound Expert Licensed User

    You have a mix of syntax from the original WebViewExtras and WebViewExtras2.

    This line (with WebViewExtras2) adds the WebView to itself as a JavascriptInterface:

    Code:
    WebviewExtras1.addJavascriptInterface(WebView1, "B4A")
    Hence the Uncaught TypeError.

    The lower case a in addJavascriptInterface looks like it's been copied from code that used the original version of WebViewExtras.

    This is an example of adding a DefaultJavascriptInterface and DefaultWebChromeClient to a WebView using WebViewExtras2:

    Code:
    WebViewExtras1.Initialize(WebView1)

    Dim JavascriptInterface1 As DefaultJavascriptInterface
    JavascriptInterface1.Initialize
    WebViewExtras1.AddJavascriptInterface(JavascriptInterface1, 
    "B4A")

    Dim WebChromeClient1 As DefaultWebChromeClient
    WebChromeClient1.Initialize(
    "WebChromeClient1")
    WebViewExtras1.SetWebChromeClient(WebChromeClient1)
    WebViewExtras2 has been updated a few times, my main reason not to have properly released WebViewExtras2 to the b4a forum has been a reluctance to handle the confustion between the old and new versions.

    Latest version of WebViewExtras2.

    Martin.
     
    eps likes this.
  11. CidTek

    CidTek Active Member Licensed User

    Progress but another stumbling block.

    I got my toast message with your declaration changes but a java error immediately popped after the toast.

    How do I set Geolocation permission and handle requests (hopefully without a popup everytime) using WebViewExtras2?

    I downloaded your latest release.


    java.lang.NullPointerException

    at uk.co.martinpearman.b4a.webkit.DefaultWebChromeClient$1.onGeolocationPermissionsShowPrompt(DefaultWebChromeClient.java:66)
    at android.webkit.CallbackProxy.handleMessage(CallbackProxy.java:558)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:5041)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
    at dalvik.system.NativeStart.main(Native Method)
     
  12. warwound

    warwound Expert Licensed User

  13. CidTek

    CidTek Active Member Licensed User

    The syntax in your example fails with your new WebViewExtras2

    Substituting B4A for the MyEventName as in
    "Sub B4A_GeolocationPermissionsRequest As Int" results in the sub name underlined in red in the IDE.

    Also "Return WebViewExtras1.GEOLOCATION_PERMISSION_ALLOW" results in an Unknown member error.

    It would be nice to have sample projects that you have for WebViewExtras rewritten for WebViewExtras2.


    Did you get my donation I sent you last week?
    What I assumed to be the return page to your site after the donation was made resulted in an html error but PayPal shows the payment was sent.
     
  14. warwound

    warwound Expert Licensed User

    @CidTek

    Take a look at this, it's a rewrite of the old WebViewExtras geolocation demo.
    Works fine here on Jelly Bean:

    Code:
    Sub Process_Globals

    End Sub

    Sub Globals
       
    '   WebChromeClient1 is a global so we can reference it in the Sub WebChromeClient1_GeoLocationPermissionsRequest
       Dim WebChromeClient1 As DefaultWebChromeClient
       
    Dim WebView1 As WebView
       
    Dim WebView2 As WebView
       
    Dim WebViewExtras1 As WebViewExtras
    End Sub

    Sub Activity_Create(FirstTime As Boolean)
       
    Activity.LoadLayout("layoutMain")
      
       WebView1.Height=
    100%y/2
       WebView1.Width=
    100%x
      
       WebViewExtras1.Initialize(WebView1)
       WebChromeClient1.Initialize(
    "WebChromeClient1")
       WebViewExtras1.SetWebChromeClient(WebChromeClient1)
      
       WebView1.LoadUrl(
    "http://html5demos.com/geo")
      
       WebView2.Top=(
    100%y/2)+1
       WebView2.Height=
    100%y/2
       WebView2.Width=
    100%x
       WebView2.LoadUrl(
    "http://html5demos.com/geo")
       
    '   no WebChromeClient is added to WebView2
    End Sub

    Sub Activity_Resume

    End Sub

    Sub Activity_Pause (UserClosed As Boolean)

    End Sub

    Sub WebChromeClient1_GeoLocationPermissionsRequest As Int
       
    '   note that the manifest has had android.permission.ACCESS_FINE_LOCATION manually added to it
       Dim Response As Int
       Response=
    Msgbox2("Allow WebView1 to use device geolocation features?""Permission required:""Allow""""Disallow"Null)
       
    If Response=DialogResponse.POSITIVE Then
         
    ToastMessageShow("Permission granted"True)
         
    Return WebChromeClient1.GEOLOCATION_PERMISSION_ALLOW
       
    Else
         
    ToastMessageShow("Permission denied"True)
         
    Return WebChromeClient1.GEOLOCATION_PERMISSION_DISALLOW
       
    End If
    End Sub
    See how GEOLOCATION_PERMISSION_ALLOW and GEOLOCATION_PERMISSION_DISALLOW are now fields of the DefaultWebChromeClient and not fields of the WebViewExtras object?

    Maybe that error was causing your Sub to be underlined in red?

    I've just uploaded an update to WebViewExtras2: http://android.martinpearman.co.uk/b4a/temp/WebViewExtras2_20131025.zip
    The update now properly checks that the GeoLocationPermissionsRequest Sub has returned an integer value, the update isn't essential but you might as well download it just so you have the latest version.

    Thanks for the donation - much appreciated.
    I keep trying to fix that Paypal redirect that occurs when someone sends me a donation but can't find where in the Paypal settings to cancel it.

    Martin.
     

    Attached Files:

Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice