把 HTML 等静态文件包裹成 APK 供离线浏览的一种方法

在电梯和高铁上有些时候网络不好,这时候刷行動裝置加载不出来就很难受。

很多时候刷手机都是访问一些网站,而很多网站都是全部由静态文件构成的。然而当你点击进主页的时候没有一次性将所有资源到下到行動裝置上,导致后续点击站内的链接需要等待加载。

有没有可能将所有资源全都下载下来供浏览器浏览呢呢?
一种方式是将所有 html,css,js 文件下载到手机,然后启动一个 darkhttpd 这样的 web server,再用浏览器导航到 localhost:8080 访问,不过这样有点繁琐。
一个跨平台程序框架 Tauri v2 提供了更容易的方式,方法如下:

使用 vanilla 模板新建工程

pnpm create tauri-app -m pnpm -t vanilla --identifier app.xjtu.rust-doc xjtu-tauri-app-rust-doc
cd xjtu-tauri-app-rust-doc
pnpm install
pnpm tauri android init

然后把包含 index.html 的静态资源目录全部放到 src 目录底下:

rsync  -av --delete ~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/share/doc/rust/html/ ./src/

参照 Android Code Signing | Tauri 修改以下文件,添加 release 编译所需的凭据信息:

src-tauri/gen/android/keystore.properties
password=7
keyAlias=xj
storeFile=/app.jks
src-tauri/gen/android/app/build.gradle.kts
import java.util.Properties
import java.io.FileInputStream

plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
    id("rust")
}

val tauriProperties = Properties().apply {
    val propFile = file("tauri.properties")
    if (propFile.exists()) {
        propFile.inputStream().use { load(it) }
    }
}

android {
    compileSdk = 34
    namespace = "app.xjtu.static_app"
    defaultConfig {
        manifestPlaceholders["usesCleartextTraffic"] = "false"
        applicationId = "app.xjtu.static_app"
        minSdk = 24
        targetSdk = 34
        versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt()
        versionName = tauriProperties.getProperty("tauri.android.versionName", "1.0")
    }
    signingConfigs {
      create("release") {
          val keystorePropertiesFile = rootProject.file("keystore.properties")
          val keystoreProperties = Properties()
          if (keystorePropertiesFile.exists()) {
              keystoreProperties.load(FileInputStream(keystorePropertiesFile))
          }

          keyAlias = keystoreProperties["keyAlias"] as String
          keyPassword = keystoreProperties["password"] as String
          storeFile = file(keystoreProperties["storeFile"] as String)
          storePassword = keystoreProperties["password"] as String
        }
    }


    buildTypes {
        getByName("debug") {
            manifestPlaceholders["usesCleartextTraffic"] = "true"
            isDebuggable = true
            isJniDebuggable = true
            isMinifyEnabled = false
            packaging {                jniLibs.keepDebugSymbols.add("*/arm64-v8a/*.so")
                jniLibs.keepDebugSymbols.add("*/armeabi-v7a/*.so")
                jniLibs.keepDebugSymbols.add("*/x86/*.so")
                jniLibs.keepDebugSymbols.add("*/x86_64/*.so")
            }
        }
        getByName("release") {
            isMinifyEnabled = true
            signingConfig = signingConfigs.getByName("release")
            proguardFiles(
                *fileTree(".") { include("**/*.pro") }
                    .plus(getDefaultProguardFile("proguard-android-optimize.txt"))
                    .toList().toTypedArray()
            )
        }
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
    buildFeatures {
        buildConfig = true
    }
}

rust {
    rootDirRel = "../../../"
}

dependencies {
    implementation("androidx.webkit:webkit:1.6.1")
    implementation("androidx.appcompat:appcompat:1.6.1")
    implementation("com.google.android.material:material:1.8.0")
    testImplementation("junit:junit:4.13.2")
    androidTestImplementation("androidx.test.ext:junit:1.1.4")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.5.0")
}

apply(from = "tauri.build.gradle.kts")

构建 APK:

tauri android build --apk --target aarch64

效果展示:

Hidden

Play Store 上面有别人不知道用什么高级方法打包的 APK:
https://play.google.com/store/apps/details?id=com.rust_doc.md_ismail_hosen
https://play.google.com/store/apps/details?id=com.rust_book.example

2 个赞

这么想想你站也可以做一个静态离线版的 app,仅浏览

好的,这是你站的所有帖子的文字和图片等富媒体资料归档在一起给人浏览的一个 APK,除了体积大了一点(1650 MiB),后续的浏览速度倒是快得飞起 :flight_departure:

https://assets.xjtu.app/pool/app.xjtu.static-app.apk

P.S. 1:静态网页是在今天用:

wget --adjust-extension --mirror --page-requisites --convert-links   --recursive  --user-agent "Googlebot" https://xjtu.app

命令爬到的。

假如把浏览器 User Agent 改成 Googlebot 也可获得同样的界面,或可直接访问:https://static.xjtu.app 感受。

P.S. 2:你站所有静态资源加在一块总共有 1GiB+,编译太费时,提示这种基于 tauri 的方式 scale badly