feat(app-ui): APP UI元素設定 Phase 1 app 端 — 解析 B014 UISet + A1 滿版套圖

- UiSkin:解析/落地(SettingsDao UISkin)/預抓(ImageGlide.preload)/套用(fileload)
- StarCloudAPI.saveSettings 加 UISet 解析
- A1(頁面跳轉中)套到 restart 畫面 restartImage(RestartHost/Restart)
- A2/A3 已在下發+落地管線,待定位對應畫面再接 UiSkin.apply

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
terrylee 2026-07-15 12:37:56 +08:00
parent b3258c2b0d
commit 569cfeac09
4 changed files with 115 additions and 0 deletions

View File

@ -1288,6 +1288,13 @@ public class StarCloudAPI {
}
}
// 6e. UISet後台APP UI 元素設定下發部位 part_key 圖片 URL
// 落地供各部位 UiSkin.apply 套用缺整個物件不動本地既有換膚
JSONObject uiSet = config.optJSONObject("UISet");
if (uiSet != null) {
com.unibuy.smartdevice.ui.tools.UiSkin.save(handlerMain.getContext(), uiSet);
}
if (devSet != null || cashSet != null || funcSet != null || hardwareSet != null || hasShoppingMode || langSet != null) {
MyApp.saveSystemSet(handlerMain.getContext());
}

View File

@ -83,6 +83,9 @@ public class RestartActivity extends AppCompatActivityAbstract {
binding = ActivityRestartBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// A1頁面跳轉中套用後台APP UI 元素設定下發的滿版圖未設定則保留預設 unibuy_transfer_page
com.unibuy.smartdevice.ui.tools.UiSkin.apply("A1", binding.restartImage);
// 🚩 重啟前統一釋放所有資源
DeviceResourceManager.getInstance().releaseAllDevices();
// 延遲幾秒後執行 App 重啟

View File

@ -103,6 +103,9 @@ public class RestartHostActivity extends AppCompatActivityAbstract {
binding = ActivityRestartHostBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// A1頁面跳轉中套用後台APP UI 元素設定下發的滿版圖未設定則保留預設 unibuy_transfer_page
com.unibuy.smartdevice.ui.tools.UiSkin.apply("A1", binding.restartImage);
httpAPI = new HttpAPI(getHandlerMain());
starCloudAPI = new com.unibuy.smartdevice.external.StarCloudAPI(getHandlerMain(), getHandlerMain());

View File

@ -0,0 +1,102 @@
package com.unibuy.smartdevice.ui.tools;
import android.content.Context;
import android.widget.ImageView;
import com.unibuy.smartdevice.database.SettingsDao;
import com.unibuy.smartdevice.structure.SettingStructure;
import org.json.JSONObject;
import java.util.Iterator;
import java.util.List;
/**
* 後台APP UI 元素設定換膚 B014 下發的 UISet部位 part_key 圖片 URL
* 落地到 SettingsDao並提供把某部位圖片套到任一 ImageView 的方法
*
* 儲存格式settingId = {@link #SETTING_ID}每個部位一列 data = [part_key, url]
* 部位無設定時保留該 view 原本的 XML 預設圖不覆蓋
*/
public class UiSkin {
public static final String SETTING_ID = "UISkin";
/**
* 解析並落地 B014 UISet整組覆蓋先刪後寫並預抓圖片到本地快取
*/
public static void save(Context ctx, JSONObject uiSet) {
if (ctx == null || uiSet == null) {
return;
}
SettingsDao dao = new SettingsDao(ctx);
try {
dao.deleteWhere(SETTING_ID);
Iterator<String> keys = uiSet.keys();
while (keys.hasNext()) {
String partKey = keys.next();
String url = uiSet.optString(partKey, "");
if (partKey == null || partKey.isEmpty() || url == null || url.isEmpty()) {
continue;
}
dao.insertOne(new SettingStructure(SETTING_ID, new String[]{partKey, url}));
// 預先下載到本地檔force=true 確保更新後重抓失敗不阻斷套用時仍會退回以 URL 直載
try {
new ImageGlide(ctx).preload(url, true);
} catch (Exception ignore) {
}
}
} catch (Exception ignore) {
} finally {
dao.close();
}
}
/**
* 取某部位設定的圖片 URL未設定回傳 null
*/
public static String getUrl(Context ctx, String partKey) {
if (ctx == null || partKey == null || partKey.isEmpty()) {
return null;
}
SettingsDao dao = new SettingsDao(ctx);
try {
List<SettingStructure> list = dao.getWhere(SETTING_ID);
if (list != null) {
for (SettingStructure s : list) {
if (partKey.equals(s.getData(0))) {
String url = s.getData(1);
return (url != null && !url.isEmpty()) ? url : null;
}
}
}
} catch (Exception ignore) {
} finally {
dao.close();
}
return null;
}
/**
* 把某部位的後台設定圖套到指定 ImageView未設定則不動保留 XML 預設圖
*/
public static void apply(String partKey, ImageView imageView) {
if (imageView == null) {
return;
}
String url = getUrl(imageView.getContext(), partKey);
if (url == null) {
return;
}
try {
new ImageGlide(imageView.getContext()).fileload(url, imageView);
} catch (Exception ignore) {
}
}
}