12

I've created Android App with the webview. When trying to sign in with Google, it first asks for username & password, then the screen with the message 'Please close this window' shows up & nothing happens.

Also, the user is not logged in.

P.S. This works absolutely fine with my mobile website which itself is ported to Android Webview App. Can anyone tell why that doesn't work? I'm completely new to Android.

Milo Chen
  • 3,617
  • 4
  • 20
  • 36
Guy in the chair
  • 1,045
  • 1
  • 13
  • 42

3 Answers3

10

Two things in webview create problems in google sign-in.

  1. Google doesn't allow us to sign-in from webview nowadays. So, User-Agent needs to be customized.
  2. Popup handling in webview isn't appropriate. So, a function override is needed.

Using custom User-Agent and an AlertDialog in WebChromeClient to handle popups solve the issues for me.

Here's the full code:

public class MainActivity extends AppCompatActivity {

    private Context contextPop;
    private WebView webViewPop;
    private AlertDialog builder;

    private String url = "https://example.com";

    private WebView webView;
    private String userAgent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        webView = findViewById(R.id.webView);
        webView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                // to continue loading a given URL in the current WebView.
                // needed to handle redirects.
                return false;
            }
        });
        webView.loadUrl(url);

        WebSettings webSettings = webView.getSettings();
        // Set User Agent
        //userAgent = System.getProperty("http.agent");
        // the upper line sometimes causes "403: disallowed user agent error"
        userAgent = "";
        webSettings.setUserAgentString(userAgent + "Your App Info/Version");

        // Enable Cookies
        CookieManager.getInstance().setAcceptCookie(true);
        if(android.os.Build.VERSION.SDK_INT >= 21)
            CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true);

        // WebView Tweaks
        webSettings.setJavaScriptEnabled(true);
        webSettings.setRenderPriority(WebSettings.RenderPriority.HIGH);
        webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
        webSettings.setAppCacheEnabled(true);
        webSettings.setDomStorageEnabled(true);
        webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
        webSettings.setUseWideViewPort(true);
        webSettings.setSaveFormData(true);
        webSettings.setEnableSmoothTransition(true);
        webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);

        // Handle Popups
        webView.setWebChromeClient(new CustomChromeClient());
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
        webSettings.setSupportMultipleWindows(true);
        contextPop = this.getApplicationContext();
    }

    @Override
    public void onBackPressed() {

        if(webView.canGoBack()) {
            webView.goBack();
        }
        else {
            //super.onBackPressed();
            // Terminate the app
            finishAffinity();
            System.exit(0);
        }
    }

    class CustomChromeClient extends WebChromeClient {

        @Override
        public boolean onCreateWindow(WebView view, boolean isDialog,
                                      boolean isUserGesture, Message resultMsg) {

            webViewPop = new WebView(contextPop);
            webViewPop.setWebViewClient(new WebViewClient() {
                @Override
                public boolean shouldOverrideUrlLoading(WebView view, String url) {
                    // to continue loading a given URL in the current WebView.
                    // needed to handle redirects.
                    return false;
                }
            });

            // Enable Cookies
            CookieManager cookieManager = CookieManager.getInstance();
            cookieManager.setAcceptCookie(true);
            if(android.os.Build.VERSION.SDK_INT >= 21) {
                cookieManager.setAcceptThirdPartyCookies(webViewPop, true);
                cookieManager.setAcceptThirdPartyCookies(webView, true);
            }

            WebSettings popSettings = webViewPop.getSettings();
            // WebView tweaks for popups
            webViewPop.setVerticalScrollBarEnabled(false);
            webViewPop.setHorizontalScrollBarEnabled(false);
            popSettings.setJavaScriptEnabled(true);
            popSettings.setSaveFormData(true);
            popSettings.setEnableSmoothTransition(true);
            // Set User Agent
            popSettings.setUserAgentString(userAgent + "Your App Info/Version");
            // to support content re-layout for redirects
            popSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);

            // handle new popups
            webViewPop.setWebChromeClient(new CustomChromeClient());

            // set the WebView as the AlertDialog.Builder’s view
            builder = new AlertDialog.Builder(MainActivity.this, AlertDialog.THEME_DEVICE_DEFAULT_LIGHT).create();
            builder.setTitle("");
            builder.setView(webViewPop);

            builder.setButton("Close", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int id) {
                    webViewPop.destroy();
                    dialog.dismiss();
                }
            });

            builder.show();
            builder.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);

            WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
            transport.setWebView(webViewPop);
            resultMsg.sendToTarget();

            return true;
        }

        @Override
        public void onCloseWindow(WebView window) {
            //Toast.makeText(contextPop,"onCloseWindow called",Toast.LENGTH_SHORT).show();
            try {
                webViewPop.destroy();
            } catch (Exception e) {
                Log.d("Webview Destroy Error: ", e.getStackTrace().toString());
            }

            try {
                builder.dismiss();
            } catch (Exception e) {
                Log.d("Builder Dismiss Error: ", e.getStackTrace().toString());
            }

        }
    }
}
  • Tested above solution on android os 8.1 and 11. On Version 8.1, it is displaying loging screen in dialog box and after login, it is stuck at "one moment please" screen ... inside dialog. One OS 11, it is displaying 403: disallowed user agent error – jkr Jan 31 '21 at 08:02
  • It turned out that the previous code doesn't handle a case. The code has been updated now. Tested on [WordPress](https://wordpress.com/) and [HackerRank](https://www.hackerrank.com/) using Android 7.1 and Android 10.0. – Risal Shahriar Shefin Feb 01 '21 at 20:35
  • This answer works on my android app. – Milo Chen Oct 26 '21 at 14:02
  • so basically you can add any text to user agent and it will work – user924 Dec 10 '21 at 13:20
6

Here is the working code:

public class MainActivity extends Activity {

protected WebView mainWebView;
    // private ProgressBar mProgress;
    private Context mContext;
    private WebView mWebviewPop;
    private FrameLayout mContainer;
    private ProgressBar progress;

    private String url = "http://m.example.com";
    private String target_url_prefix = "m.example.com";

    public void onBackPressed() {

        if (mainWebView.isFocused() && mainWebView.canGoBack()) {
            mainWebView.goBack();
        } else {
            super.onBackPressed();
            finish();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mContext = this.getApplicationContext();

        // Get main webview
        mainWebView = (WebView) findViewById(R.id.webView);

        progress = (ProgressBar) findViewById(R.id.progressBar);
        progress.setMax(100);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            mainWebView.setWebContentsDebuggingEnabled(true);
        }

        mainWebView.getSettings().setUserAgentString("example_android_app");

        // Cookie manager for the webview
        CookieManager cookieManager = CookieManager.getInstance();
        cookieManager.setAcceptCookie(true);

        // Get outer container
        mContainer = (FrameLayout) findViewById(R.id.webview_frame);
        if (!InternetConnection.checkNetworkConnection(this)) {
            showAlert(this, "No network found",
                    "Please check your internet settings.");
        } else {

            // Settings
            WebSettings webSettings = mainWebView.getSettings();
            webSettings.setJavaScriptEnabled(true);
            webSettings.setAppCacheEnabled(true);
            webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
            webSettings.setSupportMultipleWindows(true);

            mainWebView.setWebViewClient(new MyCustomWebViewClient());
            mainWebView.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY);

            mainWebView.setWebChromeClient(new MyCustomChromeClient());
            mainWebView.loadUrl(url);
        }

    }

    // @Override
    // public boolean onCreateOptionsMenu(Menu menu) {
    // // Inflate the menu; this adds items to the action bar if it is present.
    // getMenuInflater().inflate(R.menu.example_main, menu);
    // return true;
    // }

    private class MyCustomWebViewClient extends WebViewClient {

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {

            progress.setProgress(0);
            progress.setVisibility(View.VISIBLE);
            super.onPageStarted(view, url, favicon);
        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            String host = Uri.parse(url).getHost();
            Log.d("shouldOverrideUrlLoading", host);
             //Toast.makeText(MainActivity.this, host,
             //Toast.LENGTH_SHORT).show();
            if (host.equals(target_url_prefix)) {
                // This is my web site, so do not override; let my WebView load
                // the page
                if (mWebviewPop != null) {
                    mWebviewPop.setVisibility(View.GONE);
                    mContainer.removeView(mWebviewPop);
                    mWebviewPop = null;
                }
                return false;
            }

            if (host.contains("m.facebook.com") || host.contains("facebook.co")
                    || host.contains("google.co")
                    || host.contains("www.facebook.com")
                    || host.contains(".google.com")
                    || host.contains(".google.co")
                    || host.contains("accounts.google.com")
                    || host.contains("accounts.google.co.in")
                    || host.contains("www.accounts.google.com")
                    || host.contains("www.twitter.com")
                    || host.contains("secure.payu.in")
                    || host.contains("https://secure.payu.in")
                    || host.contains("oauth.googleusercontent.com")
                    || host.contains("content.googleapis.com")
                    || host.contains("ssl.gstatic.com")) {
                return false;
            }
            // Otherwise, the link is not for a page on my site, so launch
            // another Activity that handles URLs
            //Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
            //startActivity(intent);
            //return true;
            return false;
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            progress.setVisibility(View.GONE);
            super.onPageFinished(view, url);
        }

        @Override
        public void onReceivedSslError(WebView view, SslErrorHandler handler,
                SslError error) {
            Log.d("onReceivedSslError", "onReceivedSslError");
            // super.onReceivedSslError(view, handler, error);
        }
    }

    public void setValue(int progress) {
        this.progress.setProgress(progress);
    }

    public void showAlert(Context context, String title, String text) {
        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
                context);

        // set title
        alertDialogBuilder.setTitle(title);

        // set dialog message
        alertDialogBuilder.setMessage(text).setCancelable(false)
                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        // if this button is clicked, close
                        // current activity
                        finish();
                    }
                }).create().show();

    }

    private class MyCustomChromeClient extends WebChromeClient {

        @Override
        public boolean onCreateWindow(WebView view, boolean isDialog,
                boolean isUserGesture, Message resultMsg) {
            mWebviewPop = new WebView(mContext);
            mWebviewPop.setVerticalScrollBarEnabled(false);
            mWebviewPop.setHorizontalScrollBarEnabled(false);
            mWebviewPop.setWebViewClient(new MyCustomWebViewClient());
            mWebviewPop.getSettings().setJavaScriptEnabled(true);
            mWebviewPop.getSettings().setSavePassword(false);
            mWebviewPop.setLayoutParams(new FrameLayout.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT));
            mContainer.addView(mWebviewPop);
            WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
            transport.setWebView(mWebviewPop);
            resultMsg.sendToTarget();

            return true;
        }

        @Override
        public void onProgressChanged(WebView view, int newProgress) {
            // TODO Auto-generated method stub
            super.onProgressChanged(view, newProgress);
            MainActivity.this.setValue(newProgress);
        }

        @Override
        public void onCloseWindow(WebView window) {
            Log.d("onCloseWindow", "called");
        }

    }
}
Guy in the chair
  • 1,045
  • 1
  • 13
  • 42
  • I tried this code but it gets me to a blank page after login. With facebook login the code works fine, but with google+ not! Does anyone has a tip for me?? – user2494863 Nov 16 '16 at 17:21
  • 1
    Please update this answer to explain what you actually did to fix the problem. – JSutton Feb 02 '17 at 01:09
  • 1
    I am unable to login using google, getting 403 error – Nigam Patro Apr 26 '18 at 18:04
  • @NigamPatro what did you do, to overcome this error?? i am getting 403: disallowed user agent – jkr Jan 31 '21 at 08:04
  • No worries. Thanks for the reply. I have gone down the TWA route, to get the android build from web app. Google login working perfect now. – jkr Feb 01 '21 at 06:44
-1
    mainWebView.getSettings().setUserAgentString("example_android_app");

fixed it for me

just changed mainWebView to what my webview was called. In my case, i set it to

    webView.getSettings().setUserAgentString("example_android_app");