Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: setWebViewClient is not working #5419

Closed
astrocreep opened this issue Feb 9, 2022 · 8 comments · Fixed by #5919
Closed

bug: setWebViewClient is not working #5419

astrocreep opened this issue Feb 9, 2022 · 8 comments · Fixed by #5919
Labels
needs reproduction needs reproducible example to illustrate the issue platform: android type: bug A confirmed bug report

Comments

@astrocreep
Copy link

Bug Report

Capacitor Version

   Capacitor Doctor   

Latest Dependencies:

  @capacitor/cli: 3.4.0
  @capacitor/core: 3.4.0
  @capacitor/android: 3.4.0
  @capacitor/ios: 3.4.0

Installed Dependencies:

  @capacitor/ios: not installed
  @capacitor/core: 3.4.0
  @capacitor/cli: 3.4.0
  @capacitor/android: 3.4.0

[success] Android looking great! 👌

Platform(s)

Android

Current Behavior

I need to use a custom WebViewClient. I coded a new one, extending BridgeWebViewClient and set it via customn Plugin using the this.bridge.setWebVielClient(new MyCustomWebViewClient(this.bridge)); method. The custom WebViewClient isn't used by Capacitor.

Expected Behavior

My custom WebViewClient should be used instead the default one.

Code Reproduction

package com.example;

import com.getcapacitor.Plugin;
import com.getcapacitor.PluginCall;
import com.getcapacitor.PluginMethod;
import com.getcapacitor.annotation.CapacitorPlugin;

@CapacitorPlugin(name = "CustomWebViewClient")
public class CustomWebViewClient extends Plugin {

    @PluginMethod
    public void init(PluginCall call)
    {
        this.bridge.setWebViewClient(new MyCustomWebViewClient(this.bridge));

        call.resolve();
    }
}

Other Technical Details

npm --version output: 8.1.3

node --version output: v17.1.0

Additional Context

The reason for this issue is the setWebViewClient setter in Bridge.java. The new WebViewClient is only assigned to the Bridge but never set in the WebView itself. I added this to get it working here locally (needs to run in the main thread. Calling this from a plugin fails, because we are in the PluginThread):

    public void setWebViewClient(BridgeWebViewClient client) {
        this.webViewClient = client;

        Handler mainHandler = new Handler(this.getContext().getMainLooper());
        WebView webView = this.webView;
        mainHandler.post(new Runnable() {
            @Override
            public void run() {
                webView.setWebViewClient(client);
            }
        });
    }
@jcesarmobile jcesarmobile added the needs reproduction needs reproducible example to illustrate the issue label Feb 9, 2022
@Ionitron
Copy link
Collaborator

Ionitron commented Feb 9, 2022

This issue may need more information before it can be addressed. In particular, it will need a reliable Code Reproduction that demonstrates the issue.

Please see the Contributing Guide for how to create a Code Reproduction.

Thanks!
Ionitron 💙

@Ionitron Ionitron added the needs reply needs reply from the user label Feb 9, 2022
@astrocreep
Copy link
Author

https://github.com/astrocreep/capacitor-setWebViewClient

After starting this one on Android. You should see a log message:
D/APP: NEW WEB VIEW CLIENT CREATED
So the new CustomWebViewClient is created. Then an image is loaded in the index.html. I would expect that load process to be intercepted by the new client, but nothing happens. If you modify Bridge.java like I did in the initial bug report, the new client is used correctly and you can see this message:

D/APP: should override? http://localhost/logo.png
D/Capacitor: Handling local request: http://localhost/logo.png

Without the fix, you only see the second line...

@Ionitron Ionitron removed the needs reply needs reply from the user label Feb 9, 2022
@jcesarmobile
Copy link
Member

So this was thought in a way that the WebViewClient was set by the users on the bridge initialization, so it would use the users client from the beginning, instead of swapping it after initialization, in that case your code modification is not needed. But with the Capacitor 3 refactor maybe things work in a different order and that doesn't work as expected, will look into it.

If done after the initialization, it should be done like this by the user/plugin:

bridge.getWebView().setWebViewClient(new BridgeWebViewClient(bridge) {
    @Override
    public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {
        handler.proceed();
    }
});

Or at least that's what I answered on an issue long ago #2751 (comment)

@astrocreep
Copy link
Author

Can you provide an example how to setup a custom WebViewClient without a plugin? I'n my linked example I tried this:

package com.example.app;
import android.os.Bundle;
import com.getcapacitor.BridgeActivity;

public class MainActivity extends BridgeActivity {
    @Override
    public void onStart() {
        super.onStart();

        this.bridge.setWebViewClient(new CustomWebViewClient(this.bridge));
    }
}

No plugin, just a minimal MainActivity. The WebView is already set up here and the client isn't changeable. Where else could I hook in?

@jcesarmobile jcesarmobile added the type: bug A confirmed bug report label Aug 25, 2022
@jcesarmobile
Copy link
Member

It's working from plugins but not from MainActivity.java

As workaround you can use this.bridge.getWebView().setWebViewClient(new CustomWebViewClient(this.bridge)); to set the WebViewClient on the WebView directly as setting it to the bridge has no effect after bridge initialization.

@astrocreep
Copy link
Author

astrocreep commented Sep 6, 2022

Yes, this is what I'm doing now and it's working

Handler mainHandler = new Handler(this.getContext().getMainLooper());
WebView webView = this.bridge.getWebView();
mainHandler.post(new Runnable() {
    @Override
    public void run() {
        webView.setWebViewClient(client);
    }
});

But having a setter that does nothing once the initialization is complete still bothers me. Imho this is not a good design choice. If there is stuff that needs to be set up before init, better have an settings object or whatever.

@jcesarmobile
Copy link
Member

This is marked as a bug, see the type: bug label on it.

@ionitron-bot
Copy link

ionitron-bot bot commented Nov 10, 2022

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Capacitor, please create a new issue and ensure the template is fully filled out.

@ionitron-bot ionitron-bot bot locked and limited conversation to collaborators Nov 10, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
needs reproduction needs reproducible example to illustrate the issue platform: android type: bug A confirmed bug report
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants