安卓集成火狐浏览器内核

前言

手机自带的浏览器内核太低了(js获取浏览器内核navigator.userAgent),不想让用户升级自带的webview内核(受限于国内环境,很可能会不成功)。
唯一的办法是将三方内核打进包里去,如:腾讯的x5内核、火狐的geckoview内核等等。

这里介绍的就是 geckoview 内核,一般情况下都要比手机自带的要好的多!

安装依赖

安卓项目以 kotlin为例!

为项目引入geckoview依赖.

geckoview的依赖防止在火狐自己的仓库中,比如最新版本在 https://maven.mozilla.org/?prefix=maven2/org/mozilla/geckoview/geckoview/141.0.20250714153642

// MyApplication/app/build.gradle.kts
dependencies {
    // ...
    // 增加这个
     implementation("org.mozilla.geckoview:geckoview:141.0.20250714153642")
}

指定下载代理位置

如果不指定,默认从谷歌镜像仓库下载,但是如上所说,人家放在火狐自己的仓库中,所以我们要手动指定下载依赖的位置!
settings.gradle.kts是 Gradle 构建系统的核心配置文件之一,主要负责定义项目的模块结构和仓库配置,修改 MyApplication/settings.gradle.kts,增加如下

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
      // 增加这个
       maven {
          url = uri("https://maven.mozilla.org/maven2/")
       }
    }
}

使用

布局调整

修改布局文件,使用GeckoView布局,MyApplication/app/src/main/res/layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <org.mozilla.geckoview.GeckoView
        android:id="@+id/geckoView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

入口调整

入口程序中,开始使用MyApplication/app/src/main/java/com/example/myapplication/MainActivity.kt

package com.example.myapplication
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.example.myapplication.R.*
import org.mozilla.geckoview.*


class MainActivity : AppCompatActivity() {
    private lateinit var geckoView: GeckoView
    private lateinit var geckoSession: GeckoSession
    private lateinit var geckoRuntime: GeckoRuntime

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(layout.activity_main)

        // 初始化GeckoView
        geckoView = findViewById(R.id.geckoView)

        // 创建运行时环境并启用远程调试 (非必需,但是如果需要浏览器调试 webview 则需要创建个对象,并注入到下一步)
        val runtimeSettings = GeckoRuntimeSettings.Builder()
            .remoteDebuggingEnabled(true) // 启用远程调试
            .build()

        // 创建运行时环境
        geckoRuntime = GeckoRuntime.create(this, runtimeSettings)

        // 配置GeckoSession
        geckoSession = GeckoSession().apply {
            // 启用常用功能
            settings.apply {
                useTrackingProtection = true // 启用跟踪保护
                suspendMediaWhenInactive = true
                allowJavascript = true
            }

            // 打开会话
            open(geckoRuntime)
        }

        // 将Session与View绑定
        geckoView.setSession(geckoSession)

        // 加载网页
        geckoSession.loadUri("https://baidu.com")
    }
}

其它

让项目支持java插件

跟本篇主题无关,可以不看!

如果项目中使用到了纯java依赖,则可以修改 MyApplication/build.gradle.kts
在 Android 项目中,MyApplication/build.gradle.kts(项目级配置)和 MyApplication/app/build.gradle.kts(模块级配置)

plugins {
    java  // 启用 Java 编译、测试和打包功能
    alias(libs.plugins.android.application) apply false
    alias(libs.plugins.kotlin.android) apply false
}

dependencies {
    implementation("com.google.guava:guava:31.1-jre") // 普通 Java 依赖
}

更新自带内核

如果你不想把内核打包进去,以下例子是 在检测到内置的webview版本过低的时候,会跳转至谷歌商店更新内核

package com.example.myapplication

import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.webkit.WebChromeClient
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.example.myapplication.R.*

fun checkWebViewVersionAndPrompt(context: Context) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val webViewPkg = WebView.getCurrentWebViewPackage()
        val versionName = webViewPkg?.versionName
        // 查看最新内核版本 https://chromiumdash.appspot.com/releases?platform=Android

        Log.d("WebViewCheck", "WebView Package: ${webViewPkg?.packageName}, Version: $versionName")

        versionName?.let {
            val majorVersion = it.split(".")[0].toIntOrNull() ?: return
            if (majorVersion < 100) {
                // ✅ WebView 内核太旧,提示用户升级
                Toast.makeText(context, "当前 WebView ${majorVersion}版本过旧,请升级  Android WebView", Toast.LENGTH_LONG).show()

                // 打开 Chrome 的 Play 商店页面(如果是国内,也许打不开)
                val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=com.android.chrome"))
                context.startActivity(intent)
            }
        }
    } else {
        Toast.makeText(context, "系统版本较低,可能不支持最新网页特性", Toast.LENGTH_LONG).show()
    }
}

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(layout.activity_web)

        // 🟡 在加载 WebView 前检测版本
        checkWebViewVersionAndPrompt(this)

        // 创建webView
        val webView: WebView =findViewById(id.webView);
        webView.loadUrl("https://teacher.test.xiaoluxue.cn");//加载url
        webView.webViewClient = WebViewClient() // 防止调用外部浏览器
        webView.webChromeClient = WebChromeClient() // alert弹窗需要
        webView.settings.javaScriptCanOpenWindowsAutomatically = true //设置js可以直接打开窗口,如window.open(),默认为false
        webView.settings.javaScriptEnabled = true //是否允许执行js,默认为false。设置true时,会提醒可能造成XSS漏洞
        webView.settings.setSupportZoom(false) //是否可以缩放,默认true
        webView.settings.builtInZoomControls = true //是否显示缩放按钮,默认false
        webView.settings.useWideViewPort = true //设置此属性,可任意比例缩放。大视图模式
        webView.settings.loadWithOverviewMode = true //和setUseWideViewPort(true)一起解决网页自适应问题
        webView.settings.domStorageEnabled = true //DOM Storage
        webView.settings.allowFileAccessFromFileURLs = true // 处理跨域问题(主要是vue、react打包后白屏问题)
        WebView.setWebContentsDebuggingEnabled(true);
    }
}

但是这个在国内不适用!
400

不过你可以自己找打适合自己的离线安装包 apk(webview本质就是一个apk)安装即可,但是有可能会遇到系统不让你安装导致失败,因为这毕竟有点底层!

另外有人说 “AndroidX WebView”,AndroidX 并不提供 WebView 的新内核,并不会让 WebView 支持更新的 CSS / JS 特性!

开发工具使用

image

另外如果你想打包签名,可以使用此网站快速生成证书来用 !
签名包的体积产出在 MyApplication/app/release目录下

安装包体积

使用了 geckoview 之后,安装包体积增加了六百多MB。
但是可以优化,如设置仅兼容主流架构的安装包

// MyApplication/app/build.gradle.kts
android {
// ...
   defaultConfig {
        ndk {
            // 只保留这两种架构  (甚至可以只要armeabi-v7a 即32为系统的,顶多就是在64位的设备上无法充分利用性能而已)
            abiFilters.addAll(listOf("armeabi-v7a", "arm64-v8a")) 
        }
   }
}

这样安装包体积,就变成了140MB!

调试 webview

如上代码演示中,是支持调试 webview 的。
只不过需要配合火狐浏览器使用才可以,浏览器地址栏输入 about:debugging

这个 issue 有提!

总结

目前主流的独立浏览器内核集成方案:
GeckoView: 活跃维护中 Mozilla 的独立浏览器内核,支持最新网页标准,适合替代系统 WebView。
Crosswalk: 已停止维护 曾流行的集成 Chromium 内核方案,但官方已经停止维护,且体积大。
WebView (系统自带): 受限于设备厂商和系统更新 只能通过系统更新或 Google Play 更新,非 App 自带。
x5内核: 封装了较新(但也不是最新)的谷歌浏览器内核,但是收费、非开源、体积较大、和 Chromium 行为不完全一致,垃圾!

为什么现在很少有人或公司再开发此类项目,或者已有项目也逐渐停止维护?
Android WebView 自 Android 5.0+ 已内置 Chromium 并可独立更新,Crosswalk 的“内核随App走”的意义减少(但是国内不适用,因为更新要依赖google服务,国内因为爱国原因你是访问不了的)。

综上,无脑使用 GeckoView 即可!

posted @ 2025-07-23 13:22  丁少华  阅读(498)  评论(0)    收藏  举报