inject CSS to a site with webview in android inject CSS to a site with webview in android android android

inject CSS to a site with webview in android


You can't inject CSS directly however you can use Javascript to manipulate page dom.

public class MainActivity extends ActionBarActivity {  WebView webView;  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    webView = new WebView(this);    setContentView(webView);    // Enable Javascript    webView.getSettings().setJavaScriptEnabled(true);    // Add a WebViewClient    webView.setWebViewClient(new WebViewClient() {        @Override        public void onPageFinished(WebView view, String url) {            // Inject CSS when page is done loading            injectCSS();            super.onPageFinished(view, url);        }    });    // Load a webpage    webView.loadUrl("https://www.google.com");}// Inject CSS method: read style.css from assets folder// Append stylesheet to document headprivate void injectCSS() {    try {        InputStream inputStream = getAssets().open("style.css");        byte[] buffer = new byte[inputStream.available()];        inputStream.read(buffer);        inputStream.close();        String encoded = Base64.encodeToString(buffer, Base64.NO_WRAP);        webView.loadUrl("javascript:(function() {" +                "var parent = document.getElementsByTagName('head').item(0);" +                "var style = document.createElement('style');" +                "style.type = 'text/css';" +                // Tell the browser to BASE64-decode the string into your script !!!                "style.innerHTML = window.atob('" + encoded + "');" +                "parent.appendChild(style)" +                "})()");    } catch (Exception e) {        e.printStackTrace();    }}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {    // Inflate the menu; this adds items to the action bar if it is present.    getMenuInflater().inflate(R.menu.main, menu);    return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {    // Handle action bar item clicks here. The action bar will    // automatically handle clicks on the Home/Up button, so long    // as you specify a parent activity in AndroidManifest.xml.    int id = item.getItemId();    if (id == R.id.action_settings) {        return true;    }    return super.onOptionsItemSelected(item);  }}


I was able to inject css by using "evaluateJavascript" which was added to WebView in API 19 https://developer.android.com/reference/android/webkit/WebView

Example in Kotlin:

private lateinit var webView: WebViewoverride fun onCreate(savedInstanceState: Bundle?) {    super.onCreate(savedInstanceState)    //...    webView = findViewById(R.id.your_webview_name)    webView.settings.javaScriptEnabled = true    webView.webViewClient = object : WebViewClient() {        override fun onPageFinished(view: WebView, url: String) {            val css = ".menu_height{height:35px;}.. etc..." //your css as String            val js = "var style = document.createElement('style'); style.innerHTML = '$css'; document.head.appendChild(style);"            webView.evaluateJavascript(js,null)            super.onPageFinished(view, url)        }    }    webView.loadUrl("https://mywepage.com") //webpage you want to load   }

UPDATE: The code above had issues applying all of the injected CSS. After consulting with my web developer, we decided to inject the link to the CSS file instead of the CSS code itself. I changed the values of the css and js variables ->

val css = "https://mywebsite.com/css/custom_app_styles.css"val js = "var link = document.createElement('link'); link.setAttribute('href','$css'); link.setAttribute('rel', 'stylesheet'); link.setAttribute('type','text/css'); document.head.appendChild(link);"


For Kotlin Users

import this

import android.util.Base64

and this is onPageFinished code

 override fun onPageFinished(view: WebView?, url: String?) {                injectCSS()}

and this is the code to call

private fun injectCSS() {            try {                val inputStream = assets.open("style.css")                val buffer = ByteArray(inputStream.available())                inputStream.read(buffer)                inputStream.close()                val encoded = Base64.encodeToString(buffer , Base64.NO_WRAP)                webframe.loadUrl(                    "javascript:(function() {" +                            "var parent = document.getElementsByTagName('head').item(0);" +                            "var style = document.createElement('style');" +                            "style.type = 'text/css';" +                            // Tell the browser to BASE64-decode the string into your script !!!                            "style.innerHTML = window.atob('" + encoded + "');" +                            "parent.appendChild(style)" +                            "})()"                )            } catch (e: Exception) {                e.printStackTrace()            }        }