You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何向Android WebView应用注入云端托管的自定义CSS与JS

实现WebView加载远程自定义CSS/JS并自动更新的方案

我正在开发一款仅用于手机日记的Android WebView应用(学校将封禁所有原生应用),目前已实现基础的WebView加载功能,但现有网站功能不足,希望从GitHub仓库的raw.githubusercontent.com链接加载自定义CSS与JS以实现动画、特效等功能,且每次应用启动时自动更新这些文件。原实现代码如下:

package com.fluid.dairy.foss // 注:包名里的dairy应为diary,建议修正

import android.annotation.SuppressLint
import android.os.Bundle
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.activity.ComponentActivity

class MainActivity : ComponentActivity() {
    private lateinit var webView: WebView

    @SuppressLint("SetJavaScriptEnabled")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.mainactivity)
        webView = findViewById(R.id.webView)
        webView.settings.javaScriptEnabled = true
        webView.settings.domStorageEnabled = true

        webView.webViewClient = object : WebViewClient() {
            @Deprecated("Deprecated in Java")
            override fun shouldOverrideUrlLoading(view: WebView?, url: String): Boolean {
                view?.loadUrl(url)
                return true
            }
        }
        webView.loadUrl("https://e-school.ryazangov.ru")
    }
}

1. 添加网络权限

在AndroidManifest.xml中添加网络访问权限,否则无法请求远程资源:

<uses-permission android:name="android.permission.INTERNET" />

2. 引入网络请求库(推荐)

使用OkHttp简化网络请求,在模块级build.gradle的dependencies块中添加:

implementation 'com.squareup.okhttp3:okhttp:4.12.0'

3. 修改MainActivity实现资源加载与注入

以下代码实现了启动时自动拉取最新资源、页面加载完成后注入CSS/JS的功能,同时修复了原代码的过时方法:

package com.fluid.diary.foss // 修正包名拼写错误

import android.annotation.SuppressLint
import android.os.Bundle
import android.webkit.WebResourceRequest
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.activity.ComponentActivity
import okhttp3.Call
import okhttp3.Callback
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import java.io.IOException

class MainActivity : ComponentActivity() {
    private lateinit var webView: WebView
    // 替换为你的GitHub Raw资源链接
    private val CUSTOM_CSS_URL = "https://raw.githubusercontent.com/你的用户名/你的仓库/main/custom.css"
    private val CUSTOM_JS_URL = "https://raw.githubusercontent.com/你的用户名/你的仓库/main/custom.js"
    private val okHttpClient = OkHttpClient()

    @SuppressLint("SetJavaScriptEnabled")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.mainactivity)
        webView = findViewById(R.id.webView)

        // 配置WebView基础参数
        webView.settings.apply {
            javaScriptEnabled = true
            domStorageEnabled = true
            allowFileAccess = true
        }

        webView.webViewClient = object : WebViewClient() {
            // 替换过时的URL拦截方法
            override fun shouldOverrideUrlLoading(
                view: WebView?,
                request: WebResourceRequest
            ): Boolean {
                view?.loadUrl(request.url.toString())
                return true
            }

            // 页面加载完成后注入自定义资源
            override fun onPageFinished(view: WebView?, url: String?) {
                super.onPageFinished(view, url)
                loadRemoteCss()
                loadRemoteJs()
            }
        }

        // 加载目标网页
        webView.loadUrl("https://e-school.ryazangov.ru")
    }

    // 加载并注入远程CSS
    private fun loadRemoteCss() {
        val request = Request.Builder().url(CUSTOM_CSS_URL).build()
        okHttpClient.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                e.printStackTrace() // 请求失败时可添加Toast提示
            }

            override fun onResponse(call: Call, response: Response) {
                response.body?.string()?.let { cssContent ->
                    runOnUiThread {
                        // 通过JS动态添加样式标签注入CSS
                        val injectScript = """
                            var style = document.createElement('style');
                            style.type = 'text/css';
                            style.innerHTML = '$cssContent';
                            document.head.appendChild(style);
                        """.trimIndent()
                        webView.evaluateJavascript(injectScript, null)
                    }
                }
                response.close()
            }
        })
    }

    // 加载并注入远程JS
    private fun loadRemoteJs() {
        val request = Request.Builder().url(CUSTOM_JS_URL).build()
        okHttpClient.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                e.printStackTrace()
            }

            override fun onResponse(call: Call, response: Response) {
                response.body?.string()?.let { jsContent ->
                    runOnUiThread {
                        webView.evaluateJavascript(jsContent, null)
                    }
                }
                response.close()
            }
        })
    }

    // 销毁时释放WebView资源
    override fun onDestroy() {
        webView.destroy()
        super.onDestroy()
    }
}

关键说明

  • 自动更新逻辑:每次启动应用都会重新请求GitHub上的最新资源,无需手动更新应用
  • 线程安全:网络请求在后台线程执行,注入操作切换回UI线程,避免ANR
  • 错误处理:添加了请求失败的异常捕获,可根据需求替换为用户可见的提示(如Toast)
  • 包名修正:原代码包名中的dairy为拼写错误,建议改为diary避免混淆

内容的提问来源于stack exchange,提问作者Ann

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 16:38:15