inject CSS to a site with webview in android

前端 未结 4 1758
小鲜肉
小鲜肉 2020-11-28 09:02

For example I want to change the background-color of www.google.comto red. I have used webview, and my style.cssfile is i

相关标签:
4条回答
  • 2020-11-28 09:42

    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: WebView
    
    override 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);"
    
    0 讨论(0)
  • 2020-11-28 09:53

    Actually you can use WebViewClient.shouldInterceptRequest on API 11+. Example: webview shouldinterceptrequest example

    0 讨论(0)
  • 2020-11-28 09:55

    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 head
    private 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();
        }
    }
    
    @Override
    public 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;
    }
    
    @Override
    public 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);
      }
    }
    
    0 讨论(0)
  • 2020-11-28 09:56

    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()
                }
    
            }
    
    0 讨论(0)
提交回复
热议问题