Appearance
JSView 小程序本地化
JSViewApp 自 1.3.413.20230831 起支持小程序本地化运行。
无网时也可用本地缓存 / APK 内预制包启动小程序。
说明(近期重构)
对外接口名与行为保持稳定,内部存储已切换为jsv_localization_v2(以index.json为真相源,按seq管理版本,默认最多保留 3 个版本)。
旧目录cacheDir/localizationJs/不再使用,升级后会按新路径重新落盘。
推荐依赖:
groovy
implementation("com.tvcode.js_view_app:JSViewApp:1.4.792.20260908") // 使用含本地化重构的版本业务侧一般通过 SyncJSLocalizationUtil 调用(主进程直连,子进程会绑定 JSLocalizationService)。
1. 本地打包一份小程序代码到 APK
在项目根目录 build.gradle 添加插件依赖:
groovy
buildscript {
dependencies {
classpath "com.android.tools.build:gradle:4.1.3"
// 本地化打包插件
classpath 'com.qcode.jslocalizationplugin:JSLocalizationPlugin:1.1.1'
}
}在 app module 的 build.gradle 启用插件:
groovy
plugins {
id 'com.android.application'
id 'com.qcode.jslocalizationplugin'
}生成代码包:
shell
# JS_URL:小程序入口 js 地址;APP_NAME:小程序 appName
./gradlew :app:jsLocalization \
-PJS_URL=http://localhost:8077/js/main.jsv.5209aedd.mjs \
-PAPP_NAME=shijiuTv.com/TestDemoCompile产物目录:
app/build/localizationJsAsset/localizationJs/
将其中的 zip(或整个 localizationJs 目录)拷到:
app/src/main/assets/localizationJs/
命名约定:{appName 中的 / 换成 .}.zip
例如 app.qcast.cn/chipadventure → app.qcast.cn.chipadventure.zip。
必须随 APK 内置对应 Core
预制包的 app.cfg 里有 COREVERSIONRANGE。
从 asset 首次解压安装时,要求该 Core 已在设备上可用(通常随 APK 打进 embedded aar);缺失会安装失败,不会写入半截索引。
查看所需 core 版本:用实际环境的 jsv-info.json / 包内 app.cfg。
aar 找相关人员获取,例如:
groovy
repositories {
flatDir { dirs 'libs' }
}
dependencies {
// 预制引擎(版本号与 COREVERSIONRANGE 对应)
implementation(name: "jsview.core-embedded-xxxxx.full", ext: "aar")
}若宿主 minSdk 低于 aar 声明值,需在 AndroidManifest 的 tools:overrideLibrary 中增加 com.qcode.jsview.CoreEmbedded(仅编译合并,运行时仍须确认 API 兼容)。
2. 运行时获取本地化启动参数
java
SyncJSLocalizationUtil.INSTANCE.getLastLocalizationParams(
getApplicationContext(),
"shijiuTv.com/TestDemoCompile",
new ILocalizationCallback.Stub() {
@Override
public void onResult(MiniAppParams miniAppParams) {
// 使用本地化参数启动
mMainPageProxy.loadParams(miniAppParams);
}
@Override
public void onJSDownloaded(MiniAppParams miniAppParams) {
// getLast 路径不会回调
}
@Override
public void onJSNothingToUpdate() {
// getLast 路径不会回调
}
@Override
public void onException(int errorCode, String msg) {
// ERROR_CODE_CACHE_EMPTY:磁盘无可用包,且 asset 也未成功安装
// ERROR_CODE_UNKNOWN:其它失败(含 asset 所需 Core 未随 APK 内置)
}
});getLastLocalizationParams 逻辑
mermaid
flowchart TD
A[getLastLocalizationParams] --> B[读 index.json 列出磁盘完整包]
B --> C{有候选?}
C -->|是| D[current 优先,其余按 seq 降序]
D --> E[逐个确保 Core 可用]
E -->|成功| F[设为 current 并返回 MiniAppParams]
E -->|失败| G[尝试下一版本]
G --> E
C -->|否| H[尝试 assets 预制 zip]
H -->|Core 已内置| I[解压 commit 后返回]
H -->|Core 缺失 / 无 zip| J[onException CACHE_EMPTY / UNKNOWN]要点:
- 磁盘包需同时满足:
READY+app.cfg+dist/且 dist 结构合法。 - 已是
current的命中不会无故增加seq;只有切换到其它版本(promote)才会刷新seq。 - 磁盘都不可用时才解压 asset;asset 安装要求 Core 已内置,不会联网补 Core。
- 有网时,对索引里的旧包可尝试补下缺失 Core 后再用。
3. 更新本地化小程序
空闲时可主动更新:
java
private void doCheckUpdate() {
MiniAppParams miniAppParams = new MiniAppParams();
miniAppParams.setUrl("http://192.168.0.27:8077/js/main.jsv.5209aedd.mjs");
// 可选;不设则从同级 jsv-info.json 解析 AppName
// miniAppParams.setAppName("shijiuTv.com/TestDemoCompile");
SyncJSLocalizationUtil.INSTANCE.doDownloadJS(
getApplicationContext(),
miniAppParams,
new ILocalizationCallback.Stub() {
@Override
public void onResult(MiniAppParams miniAppParams) {
// doDownload 路径不会回调
}
@Override
public void onJSDownloaded(MiniAppParams miniAppParams) {
// 已下载/安装或切换到其它已有版本
}
@Override
public void onJSNothingToUpdate() {
// 目标版本已是 current 且完整,无需更新(不 bump seq)
}
@Override
public void onException(int errorCode, String msg) {
// ERROR_CODE_FAIL_APP_NAME:appName 与远端 jsv-info 不一致
// ERROR_CODE_NETWORK_DISCONNECT:无网
// ERROR_CODE_UNKNOWN:其它
}
});
}doDownloadJS 逻辑
mermaid
flowchart TD
A[doDownloadJS] --> B{有网?}
B -->|否| C[onException NETWORK_DISCONNECT]
B -->|是| D[拉 jsv-info / 校验 AppName]
D --> E{本地已有该版本且完整?}
E -->|是且已是 current| F[onJSNothingToUpdate]
E -->|是但非 current| G[切换为 current + bump seq → onJSDownloaded]
E -->|否| H[并行: 下 Core + 下 engine/dist.dat]
H --> I[staging 校验后 commit]
I --> J[淘汰超出 maxVersions 的旧包]
J --> K[onJSDownloaded]要点:
- 安装走
staging → 校验 → commit,失败清理 staging,避免半截包。 - 默认每个 app 最多保留 3 个版本(按
seq淘汰非 current)。 - Core 下载可与包下载并行;安装失败会取消等待,避免堵死本地化线程。
4. 磁盘布局(实现细节)
每个小程序一份目录:
text
filesDir/jsv_localization_v2/{safeAppName}/
index.json # currentVersion / nextSeq / entries
staging/ # 安装临时区
packages/{version}/
READY
app.cfg
engine.js? # 可选
dist/index.json 中每个版本记录 core、bytes、seq、ready 等;版本新旧以单调递增的 seq 为准,不依赖文件时间戳。
5. 其它 API
java
// 清空某 app 的本地化缓存(v2 目录整棵删除)
SyncJSLocalizationUtil.INSTANCE.clearLocalVersion(context, appName);6. 错误码
| 常量 | 含义 |
|---|---|
ERROR_CODE_CACHE_EMPTY | 本地无可用包,asset 也未装上 |
ERROR_CODE_FAIL_APP_NAME | 传入 appName 与远端包不一致 |
ERROR_CODE_NETWORK_DISCONNECT | 更新时无网络 |
ERROR_CODE_UNKNOWN | 其它失败(含 asset Core 未内置等) |