如何向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
相关产品推荐
相关产品推荐

