35

I'm trying to make a app with WebView, but the website is using https, but the content (ex. mp3 file) uses http, so Android Lollipop won't load it because it is "Mixed Content". I tried to use onReceivedSslError handler.proceed();, but it doesn't load anything. Is there a way to fix it? or could I just make all websites loaded use http, so It doesn't show any errors?

8 Answers 8

52

Since Pie (API 29), all non-HTTPS traffic in app is now disabled by default.

If you're targeting API level 26 or above, you must first enable it in the manifest file. Add

android:usesCleartextTraffic="true"

into <application> tag.


Since Lollipop (API 21), WebView blocks all mixed content by default.

To change this behaviour, when you are targeting API level 21 or above, use:

webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);

In this mode, the WebView will attempt to be compatible with the approach of a modern web browser with regard to mixed content. Some insecure content may be allowed to be loaded by a secure origin and other types of content will be blocked. The types of content are allowed or blocked may change release to release and are not explicitly defined.

In practice this should allow loading of images, videos, music etc. - all content that has low probability of being major security threat, when tampered/replaced by malicious third-party.


Alternatively use (strongly discouraged):

webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);

In this mode, the WebView will allow a secure origin to load content from any other origin, even if that origin is insecure. This is the least secure mode of operation for the WebView, and where possible apps should not set this mode.

5
  • 3
    I am running into the same problem. I am targeting a device that is api19 and the above code only works on api 21, Seem to be in the sweet spot where it just doesnt work either way. Any ideas?
    – Danimal
    Nov 25, 2016 at 16:23
  • 3
    I'm facing the same issue and this solution doesn't seem to work. Any new ideas?
    – returnvoid
    Apr 11, 2017 at 1:44
  • 4
    This should not be accepted answer. It doesn't seems to work.
    – DroidDev
    May 8, 2017 at 17:03
  • 1
    Hmm, does not work on API 28 for me. Tested 27, 26, 25, these work fine.
    – Harri
    Sep 5, 2018 at 7:14
  • 3
    Android 9 and higher requires android:usesCleartextTraffic="true" attribute in your application tag of AndroidManifest.xml additionally to the webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); flag.
    – konata
    Jul 4, 2019 at 10:36
9

If your min API is less than 21 and cannot call setMixedContentMode directly, you can use reflection:

try {
    Method m = WebSettings.class.getMethod("setMixedContentMode", int.class);
    if ( m == null ) {
        Log.e("WebSettings", "Error getting setMixedContentMode method");
    }
    else {
        m.invoke(webView.getSettings(), 2); // 2 = MIXED_CONTENT_COMPATIBILITY_MODE
        Log.i("WebSettings", "Successfully set MIXED_CONTENT_COMPATIBILITY_MODE");
    }
}
catch (Exception ex) {
    Log.e("WebSettings", "Error calling setMixedContentMode: " + ex.getMessage(), ex);
}
3
  • where should this code be? how do you access webView?
    – syonip
    May 28, 2019 at 9:50
  • @syonip It depends on how you created the WebView. You can get a reference using the findViewById() method if you're in an Activity. You can put the block of code anywhere before you loading data into it (.e.g onResume() of your Activity)
    – Andrew Lim
    May 31, 2019 at 12:31
  • @syonip In case of Cordova apps it should be in MainActivity.java as shown in my answer.
    – andreszs
    Nov 13, 2023 at 13:41
8

In android pie in addition to setting the mixed content mode, you also need to set the android:usesCleartextTraffic attribute in the AndroidManifest.

In your AndroidManifest.xml do:

<application
    ....
    android:usesCleartextTraffic="true"
    ...>

and when setting up the webview, do:

webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
2
  • This should be the right answer ! Thank you so much. This attribute android:usesCleartextTraffic is needed in the AndroidManifest.xml file !
    – Fcps
    Mar 9, 2019 at 18:10
  • Even though the default value is true, I needed this explicitly set to true also
    – Juddling
    Mar 17, 2019 at 12:33
4

to load it conditionally on API >= 21, you don't have to use reflection.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {   
          webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
}
2

I've recently migrated from Crosswalk to use the native WebView.

Had to fight with this issue for a few hours. The fix was to run clearCache() prior to setting the settings.

webView.clearCache(false);  // <-- DO THIS FIRST
webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
1

Go to manifest.xml and add the following line.

android:usesCleartextTraffic="true"

And in Java file of webview add this code.

webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
0

If you are running into this problem, just make sure you have installed the Ionic's WebView Cordova Plugin (https://github.com/ionic-team/cordova-plugin-ionic-webview). The easiest way is to check your package.json.

Once installed:

  1. Open your config.xml file

  2. Check if you have an entry for <preference name="Scheme">

  3. If you do, check that the value is "https".

  4. If you don't have it, then add this line: <preference name="Scheme" value="https" />

  5. Add this line: <preference name="MixedContentMode" value="0" />

This solved the problem for me.

1
  • It seems I spoke too quickly. This solution worked... one time; at soon as I rebuilt the app, it started to block my http requests again. :( Apr 28, 2021 at 14:16
0

For those using vanilla Cordova, you'll need to add the onResume function in your MainActivity.java and call setMixedContent from there as shown here.

    @Override
    public void onResume() {
        super.onResume();
        // Add the following lines to enable mixed content mode
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            WebView webView = (WebView) appView.getView(); // Change from getEngine() to getView()
            WebSettings settings = webView.getSettings();
            settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        }
    }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.