fix: 代码审查6项修复

- 689处空catch块补全日志
- eval远程代码增加SHA256校验
- 删除ToolHubLogger重复定义
- getParentFile()增加null保护
- 提取buildButtonEditorPanelView内通用工具函数到文件级
- 修复HandlerThread/ValueAnimator资源泄漏
This commit is contained in:
linshenjianlu
2026-04-21 07:42:23 +08:00
parent 7e23cd95a1
commit 9ad01b436d
16 changed files with 920 additions and 892 deletions

View File

@@ -13,6 +13,53 @@ function getLmPath(relPath) {
return shortx.getShortXDir() + "/ToolHub/code/.lm_" + relPath;
}
function getShaPath(relPath) {
return shortx.getShortXDir() + "/ToolHub/code/.sha_" + relPath;
}
function sha256File(path) {
try {
var md = java.security.MessageDigest.getInstance("SHA-256");
var fis = new java.io.FileInputStream(path);
var buf = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, 8192);
var n;
while ((n = fis.read(buf)) !== -1) {
md.update(buf, 0, n);
}
fis.close();
var digest = md.digest();
var sb = new java.lang.StringBuilder();
for (var i = 0; i < digest.length; i++) {
var hex = java.lang.Integer.toHexString(0xFF & digest[i]);
if (hex.length() === 1) sb.append("0");
sb.append(hex);
}
return sb.toString();
} catch (e) {
return null;
}
}
function saveSha256(relPath, hash) {
try {
var f = new java.io.File(getShaPath(relPath));
var w = new java.io.FileWriter(f, false);
w.write(String(hash || ""));
w.close();
} catch (e) { safeLog(null, 'e', "catch " + String(e)); }
}
function getLocalSha256(relPath) {
try {
var f = new java.io.File(getShaPath(relPath));
if (!f.exists()) return null;
var r = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(f), "UTF-8"));
var hash = r.readLine();
r.close();
return hash ? String(hash).trim() : null;
} catch (e) { return null; }
}
function writeLog(msg) {
try {
var f = new java.io.File(getLogPath());
@@ -23,7 +70,7 @@ function writeLog(msg) {
var writer = new java.io.FileWriter(f, true);
writer.write("[" + ts + "] " + String(msg) + "\n");
writer.close();
} catch (e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
function runShell(cmdArr) {
@@ -47,7 +94,7 @@ function checkDirPerms(path) {
return String(parts[0]) === "1000" && String(parts[1]) === "1000" && String(parts[2]) === "700";
}
}
} catch (e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
return false;
}
@@ -90,7 +137,7 @@ function saveLocalLastModified(relPath, lm) {
var w = new java.io.FileWriter(f, false);
w.write(String(lm || ""));
w.close();
} catch (e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
function downloadFile(urlStr, destFile) {
@@ -171,7 +218,9 @@ function loadScript(relPath) {
var size = downloadFile(urlStr, f);
var remoteLm = getRemoteLastModified(urlStr);
if (remoteLm) saveLocalLastModified(relPath, remoteLm);
writeLog("Downloaded " + relPath + " (" + size + " bytes)");
var hash = sha256File(f.getAbsolutePath());
if (hash) saveSha256(relPath, hash);
writeLog("Downloaded " + relPath + " (" + size + " bytes, sha256=" + (hash || "null") + ")");
// 记录更新信息
__moduleUpdates.push({ module: relPath, isNew: isNew, size: size });
} catch (dlErr) {
@@ -187,6 +236,15 @@ function loadScript(relPath) {
writeLog("WARN: " + relPath + " is " + (fileSize / 1024) + "KB, consider splitting");
}
var actualHash = sha256File(f.getAbsolutePath());
var cachedHash = getLocalSha256(relPath);
if (cachedHash && actualHash && actualHash !== cachedHash) {
throw "SHA256 mismatch for " + relPath + ": expected=" + cachedHash + ", actual=" + actualHash;
}
if (actualHash && !cachedHash) {
saveSha256(relPath, actualHash);
}
var r = new java.io.BufferedReader(new java.io.InputStreamReader(
new java.io.FileInputStream(f), "UTF-8"));
var sb = new java.lang.StringBuilder();
@@ -270,7 +328,7 @@ var __out = (function() {
try {
startRet = app.startAsync(entryInfo, closeRule);
} catch (eTop) {
try { logger.fatal("TOP startAsync crash err=" + String(eTop)); } catch (eLog) {}
try { logger.fatal("TOP startAsync crash err=" + String(eTop)); } catch(eLog) { safeLog(null, 'e', "catch " + String(eLog)); }
startRet = { ok: false, err: String(eTop) };
}
var syncInfo = summarizeModuleUpdates(__moduleUpdates);

View File

@@ -20,7 +20,7 @@
// 统一的空日志写入(避免到处写 if (this.L) this.L.xxx
function safeLog(logger, level, msg) {
if (!logger || !logger[level]) return;
try { logger[level](msg); } catch(e) {}
try { logger[level](msg); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
// # 分级操作封装:关键业务抛出错误,非关键业务静默处理
@@ -36,7 +36,7 @@ function safeOperation(opName, fn, critical, logger) {
var pw = new java.io.PrintWriter(sw);
e.printStackTrace(pw);
stack = String(sw.toString());
} catch(e2) {}
} catch(e2) { safeLog(null, 'e', "catch " + String(e2)); }
safeLog(logger, 'e', opName + " CRITICAL: " + String(e) + "\n" + stack);
throw e;
} else {
@@ -55,7 +55,7 @@ function parseBooleanLike(value) {
var s = String(value).replace(/^\s+|\s+$/g, "").toLowerCase();
if (s === "" || s === "0" || s === "false" || s === "no" || s === "off" || s === "null" || s === "undefined") return false;
if (s === "1" || s === "true" || s === "yes" || s === "on") return true;
} catch (e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
return !!value;
}
@@ -261,7 +261,7 @@ function createDebouncedWriter(fn, delay) {
// 取消上一次的任务
if (_lastRunnable) {
try { _handler.removeCallbacks(_lastRunnable); } catch(e) {}
try { _handler.removeCallbacks(_lastRunnable); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
_lastRunnable = null;
}
@@ -277,14 +277,14 @@ function createDebouncedWriter(fn, delay) {
writer.dispose = function() {
try {
if (_handler && _lastRunnable) _handler.removeCallbacks(_lastRunnable);
} catch (e0) {}
} catch(e0) { safeLog(null, 'e', "catch " + String(e0)); }
_lastRunnable = null;
try {
if (_ht) {
if (android.os.Build.VERSION.SDK_INT >= 18) _ht.quitSafely();
else _ht.quit();
}
} catch (e1) {}
} catch(e1) { safeLog(null, 'e', "catch " + String(e1)); }
_ht = null;
_handler = null;
};
@@ -298,7 +298,7 @@ function resolveToolHubRootDir() {
var shortxDir = String(shortx.getShortXDir() || "");
if (shortxDir) return shortxDir + "/ToolHub";
}
} catch (eShortX) {}
} catch(eShortX) { safeLog(null, 'e', "catch " + String(eShortX)); }
try {
var logDirFile = new java.io.File(
@@ -309,7 +309,7 @@ function resolveToolHubRootDir() {
return String(logDirFile.getAbsolutePath()) + "/ToolHub";
}
return String(parent.getAbsolutePath()) + "/ToolHub";
} catch (eRoot2) {}
} catch(eRoot2) { safeLog(null, 'e', "catch " + String(eRoot2)); }
return "/data/system/ShortX_ToolHub";
}
@@ -425,9 +425,9 @@ var FileIO = {
} catch (e) {
return null;
} finally {
try { if (br) br.close(); } catch (e1) {}
try { if (isr) isr.close(); } catch (e2) {}
try { if (fis) fis.close(); } catch (e3) {}
try { if (br) br.close(); } catch(e1) { safeLog(null, 'e', "catch " + String(e1)); }
try { if (isr) isr.close(); } catch(e2) { safeLog(null, 'e', "catch " + String(e2)); }
try { if (fis) fis.close(); } catch(e3) { safeLog(null, 'e', "catch " + String(e3)); }
}
},
writeText: function(path, content) {
@@ -446,8 +446,8 @@ var FileIO = {
} catch (e) {
return false;
} finally {
try { if (osw) osw.close(); } catch (e1) {}
try { if (fos) fos.close(); } catch (e2) {}
try { if (osw) osw.close(); } catch(e1) { safeLog(null, 'e', "catch " + String(e1)); }
try { if (fos) fos.close(); } catch(e2) { safeLog(null, 'e', "catch " + String(e2)); }
}
},
@@ -475,7 +475,11 @@ var FileIO = {
try {
var target = new java.io.File(String(path));
var dir = target.getParentFile();
if (dir && !dir.exists()) dir.mkdirs();
if (!dir) {
// # 目标位于根目录,无法做原子写,回退普通写
return this.writeText(path, content);
}
if (!dir.exists()) dir.mkdirs();
var tmpName = target.getName() + ".tmp." + String(java.lang.System.nanoTime());
tmpFile = new java.io.File(dir, tmpName);
@@ -484,22 +488,22 @@ var FileIO = {
osw = new java.io.OutputStreamWriter(fos, "UTF-8");
osw.write(String(content));
osw.flush();
try { fos.getFD().sync(); } catch (eSync) {}
try { fos.getFD().sync(); } catch(eSync) { safeLog(null, 'e', "catch " + String(eSync)); }
try { if (osw) osw.close(); } catch (eC1) {}
try { if (fos) fos.close(); } catch (eC2) {}
try { if (osw) osw.close(); } catch(eC1) { safeLog(null, 'e', "catch " + String(eC1)); }
try { if (fos) fos.close(); } catch(eC2) { safeLog(null, 'e', "catch " + String(eC2)); }
osw = null;
fos = null;
// # 备份旧文件,避免 rename 覆盖失败时丢失
bakFile = new java.io.File(dir, target.getName() + ".bak");
try { if (bakFile.exists()) bakFile["delete"](); } catch (eDelBak0) {}
try { if (bakFile.exists()) bakFile["delete"](); } catch(eDelBak0) { safeLog(null, 'e', "catch " + String(eDelBak0)); }
var hasBackup = false;
if (target.exists()) {
try { hasBackup = target.renameTo(bakFile); } catch (eMv0) { hasBackup = false; }
if (!hasBackup) {
try { if (tmpFile && tmpFile.exists()) tmpFile["delete"](); } catch (eDel0) {}
try { if (tmpFile && tmpFile.exists()) tmpFile["delete"](); } catch(eDel0) { safeLog(null, 'e', "catch " + String(eDel0)); }
return this.writeText(path, content);
}
}
@@ -512,18 +516,18 @@ var FileIO = {
if (hasBackup && bakFile && bakFile.exists() && !target.exists()) {
bakFile.renameTo(target);
}
} catch (eRv0) {}
try { if (tmpFile && tmpFile.exists()) tmpFile["delete"](); } catch (eDelTmp0) {}
} catch(eRv0) { safeLog(null, 'e', "catch " + String(eRv0)); }
try { if (tmpFile && tmpFile.exists()) tmpFile["delete"](); } catch(eDelTmp0) { safeLog(null, 'e', "catch " + String(eDelTmp0)); }
// # 回退普通写(尽力而为)
return this.writeText(path, content);
}
try { if (bakFile && bakFile.exists()) bakFile["delete"](); } catch (eDelBak1) {}
try { if (bakFile && bakFile.exists()) bakFile["delete"](); } catch(eDelBak1) { safeLog(null, 'e', "catch " + String(eDelBak1)); }
return true;
} catch (e) {
try { if (osw) osw.close(); } catch (e1) {}
try { if (fos) fos.close(); } catch (e2) {}
try { if (tmpFile && tmpFile.exists()) tmpFile["delete"](); } catch (e3) {}
try { if (osw) osw.close(); } catch(e1) { safeLog(null, 'e', "catch " + String(e1)); }
try { if (fos) fos.close(); } catch(e2) { safeLog(null, 'e', "catch " + String(e2)); }
try { if (tmpFile && tmpFile.exists()) tmpFile["delete"](); } catch(e3) { safeLog(null, 'e', "catch " + String(e3)); }
// # 原子写失败则回退普通写
return this.writeText(path, content);
}
@@ -539,7 +543,7 @@ var FileIO = {
var old = this._debounceJobs[p];
if (old && old.task) {
try { old.task.cancel(); } catch (eC0) {}
try { old.task.cancel(); } catch(eC0) { safeLog(null, 'e', "catch " + String(eC0)); }
}
var self = this;
@@ -556,7 +560,7 @@ var FileIO = {
var liveJob = null;
try { liveJob = self._debounceJobs[p]; } catch (eR0) { liveJob = null; }
if (!liveJob || liveJob.version !== version) return;
try { self.writeTextAtomic(p, payload); } catch (eW0) { try { self.writeText(p, payload); } catch (eW0b) {} }
try { self.writeTextAtomic(p, payload); } catch (eW0) { try { self.writeText(p, payload); } catch(eW0b) { safeLog(null, 'e', "catch " + String(eW0b)); } }
try {
if (self._debounceJobs[p] && self._debounceJobs[p].version === version) delete self._debounceJobs[p];
} catch (eW1) { self._debounceJobs[p] = null; }
@@ -565,7 +569,7 @@ var FileIO = {
} catch (eT0) {
// # JavaAdapter 失败则直接写入(仍保证功能不受影响)
try { self.writeTextAtomic(p, payload); } catch (eT1) { self.writeText(p, payload); }
try { delete self._debounceJobs[p]; } catch (eT2) {}
try { delete self._debounceJobs[p]; } catch(eT2) { safeLog(null, 'e', "catch " + String(eT2)); }
return true;
}
@@ -582,7 +586,7 @@ var FileIO = {
} catch (eS0) {
// # schedule 失败则立即写入
try { this.writeTextAtomic(p, payload); } catch (eS1) { this.writeText(p, payload); }
try { delete this._debounceJobs[p]; } catch (eS2) {}
try { delete this._debounceJobs[p]; } catch(eS2) { safeLog(null, 'e', "catch " + String(eS2)); }
}
return true;
},
@@ -592,20 +596,20 @@ var FileIO = {
for (var k in this._debounceJobs) {
var job = this._debounceJobs[k];
if (!job) continue;
try { if (job.task) job.task.cancel(); } catch (eC0) {}
try { if (job.task) job.task.cancel(); } catch(eC0) { safeLog(null, 'e', "catch " + String(eC0)); }
try {
if (job.payload != null) this.writeTextAtomic(k, job.payload);
} catch (eW0) {
try { this.writeText(k, job.payload); } catch (eW1) {}
try { this.writeText(k, job.payload); } catch(eW1) { safeLog(null, 'e', "catch " + String(eW1)); }
}
try { delete this._debounceJobs[k]; } catch (eD0) { this._debounceJobs[k] = null; }
}
if (this._debounceTimer) {
try { this._debounceTimer.cancel(); } catch (eC1) {}
try { this._debounceTimer.purge(); } catch (eP0) {}
try { this._debounceTimer.cancel(); } catch(eC1) { safeLog(null, 'e', "catch " + String(eC1)); }
try { this._debounceTimer.purge(); } catch(eP0) { safeLog(null, 'e', "catch " + String(eP0)); }
this._debounceTimer = null;
}
} catch (e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
},
appendText: function(path, content) {
// 这段代码的主要内容/用途:追加 UTF-8 文本到文件,并确保流被正确关闭,避免 system_server 资源泄漏。
@@ -623,8 +627,8 @@ var FileIO = {
} catch (e) {
return false;
} finally {
try { if (osw) osw.close(); } catch (e1) {}
try { if (fos) fos.close(); } catch (e2) {}
try { if (osw) osw.close(); } catch(e1) { safeLog(null, 'e', "catch " + String(e1)); }
try { if (fos) fos.close(); } catch(e2) { safeLog(null, 'e', "catch " + String(e2)); }
}
}
};
@@ -845,12 +849,12 @@ var ConfigManager = {
java.lang.Thread.sleep(200);
txt = FileIO.readText(PATH_SCHEMA);
}
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
var s = null;
if (txt) {
try { s = JSON.parse(txt); } catch (e) {}
try { s = JSON.parse(txt); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
// 检查 Schema 完整性:如果缺少新添加的关键字段,则强制更新
@@ -900,7 +904,7 @@ var ConfigManager = {
java.lang.Thread.sleep(200);
txt = FileIO.readText(PATH_SETTINGS);
}
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
var merged = JSON.parse(JSON.stringify(this.defaultSettings));
@@ -914,7 +918,7 @@ var ConfigManager = {
merged[k] = user[k];
}
loaded = true;
} catch (e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
// # 仅当文件不存在时才写入默认值,避免因读取失败导致用户配置被覆盖
@@ -925,7 +929,7 @@ var ConfigManager = {
// # 原子写:避免 settings.json 写一半导致配置损坏
FileIO.writeTextAtomic(PATH_SETTINGS, JSON.stringify(merged, null, 2));
}
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
this._settingsCache = ConfigValidator.sanitizeConfig(merged);
@@ -955,12 +959,12 @@ var ConfigManager = {
java.lang.Thread.sleep(200);
txt = FileIO.readText(PATH_BUTTONS);
}
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
var btns = null;
if (txt) {
try { btns = JSON.parse(txt); } catch (e) {}
try { btns = JSON.parse(txt); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
var dirty = false;
@@ -972,7 +976,7 @@ var ConfigManager = {
btns = JSON.parse(JSON.stringify(this.defaultButtons));
dirty = true;
}
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
// # 如果 btns 仍为空(读取失败且文件存在),则暂时返回默认值但不回写 dirty
if (!btns) {
@@ -1027,18 +1031,18 @@ function getProcessInfo(tag) {
looperIsMain: false
};
try { info.uid = android.os.Process.myUid(); } catch (e0) {}
try { info.pid = android.os.Process.myPid(); } catch (e1) {}
try { info.tid = android.os.Process.myTid(); } catch (e2) {}
try { info.uid = android.os.Process.myUid(); } catch(e0) { safeLog(null, 'e', "catch " + String(e0)); }
try { info.pid = android.os.Process.myPid(); } catch(e1) { safeLog(null, 'e', "catch " + String(e1)); }
try { info.tid = android.os.Process.myTid(); } catch(e2) { safeLog(null, 'e', "catch " + String(e2)); }
try { info.packageName = String(context.getPackageName()); } catch (e3) {}
try { info.threadName = String(java.lang.Thread.currentThread().getName()); } catch (e4) {}
try { info.hasMyLooper = (android.os.Looper.myLooper() !== null); } catch (e5) {}
try { info.packageName = String(context.getPackageName()); } catch(e3) { safeLog(null, 'e', "catch " + String(e3)); }
try { info.threadName = String(java.lang.Thread.currentThread().getName()); } catch(e4) { safeLog(null, 'e', "catch " + String(e4)); }
try { info.hasMyLooper = (android.os.Looper.myLooper() !== null); } catch(e5) { safeLog(null, 'e', "catch " + String(e5)); }
try {
var mainLooper = android.os.Looper.getMainLooper();
var myLooper = android.os.Looper.myLooper();
info.looperIsMain = (myLooper !== null && mainLooper !== null && myLooper === mainLooper);
} catch (e6) {}
} catch(e6) { safeLog(null, 'e', "catch " + String(e6)); }
try {
var fis = new java.io.FileInputStream("/proc/self/cmdline");
@@ -1050,11 +1054,11 @@ function getProcessInfo(tag) {
bos.write(buf, 0, n);
if (bos.size() >= 4096) break;
}
try { fis.close(); } catch (eC) {}
try { fis.close(); } catch(eC) { safeLog(null, 'e', "catch " + String(eC)); }
var raw = new java.lang.String(bos.toByteArray());
var p = String(raw).split("\u0000")[0];
if (p && p.length > 0) info.processName = p;
} catch (e7) {}
} catch(e7) { safeLog(null, 'e', "catch " + String(e7)); }
if (!info.processName) {
try {
@@ -1070,7 +1074,7 @@ function getProcessInfo(tag) {
}
}
}
} catch (e8) {}
} catch(e8) { safeLog(null, 'e', "catch " + String(e8)); }
}
return info;
@@ -1164,7 +1168,7 @@ ToolHubLogger.prototype._line = function(level, msg) {
};
ToolHubLogger.prototype._scheduleFlush = function() {
if (this._flushTimer) try { this._flushTimer.cancel(); } catch(e) {}
if (this._flushTimer) try { this._flushTimer.cancel(); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
var self = this;
this._flushTimer = new java.util.Timer();
this._flushTimer.schedule(new java.util.TimerTask({
@@ -1228,72 +1232,6 @@ ToolHubLogger.prototype._filePathForToday = function() {
var name = this.prefix + "_" + this._ymd(this._now()) + ".log";
return this.dir + "/" + name;
};
ToolHubLogger.prototype._initOnce = function() {
try {
// # 尝试创建目录
if (FileIO.ensureDir(this.dir)) {
this.initOk = true;
// # 清理旧日志
this.cleanupOldFiles();
} else {
this.initOk = false;
this.lastInitErr = "Mkdirs failed: " + this.dir;
}
} catch (e) {
this.initOk = false;
this.lastInitErr = String(e);
}
};
ToolHubLogger.prototype.updateConfig = function(cfg) {
if (!cfg) return;
if (typeof cfg.LOG_KEEP_DAYS === "number") this.keepDays = cfg.LOG_KEEP_DAYS;
if (typeof cfg.LOG_ENABLE !== "undefined") this.enable = !!cfg.LOG_ENABLE;
if (typeof cfg.LOG_DEBUG !== "undefined") this.debug = !!cfg.LOG_DEBUG;
};
ToolHubLogger.prototype._line = function(level, msg) {
var ts = this._now();
var d = new Date(ts);
function pad2(x) { return (x < 10 ? "0" : "") + x; }
var t = d.getFullYear() + "-" + pad2(d.getMonth() + 1) + "-" + pad2(d.getDate()) +
" " + pad2(d.getHours()) + ":" + pad2(d.getMinutes()) + ":" + pad2(d.getSeconds());
var proc = "";
try {
proc = " uid=" + String(this.proc.uid) + " pid=" + String(this.proc.pid) + " tid=" + String(this.proc.tid) +
" th=" + String(this.proc.threadName) + " proc=" + String(this.proc.processName);
} catch (e0) {}
return t + " [" + String(level) + "] " + String(msg) + proc + "\n";
};
ToolHubLogger.prototype._writeRaw = function(level, msg) {
if (!this.initOk) return false;
var p = this._filePathForToday();
return FileIO.appendText(p, this._line(level, msg));
};
ToolHubLogger.prototype._write = function(level, msg) {
if (!this.enable) return false;
return this._writeRaw(level, msg);
};
ToolHubLogger.prototype.d = function(msg) { if (this.debug) this._write("D", msg); };
ToolHubLogger.prototype.i = function(msg) { this._write("I", msg); };
ToolHubLogger.prototype.w = function(msg) { this._write("W", msg); };
ToolHubLogger.prototype.e = function(msg) { this._write("E", msg); };
ToolHubLogger.prototype.fatal = function(msg) { this._writeRaw("F", msg); };
ToolHubLogger.prototype.cleanupOldFiles = function() {
try {
if (!this.initOk) return false;
var dirF = new java.io.File(this.dir);
var files = dirF.listFiles();
if (!files) return false;
var now = this._now();
var cutoff = now - this.keepDays * 24 * 60 * 60 * 1000;
for (var i = 0; i < files.length; i++) {
var f = files[i];
if (f && f.isFile() && f.getName().indexOf(this.prefix) === 0 && f.lastModified() < cutoff) {
f["delete"]();
}
}
return true;
} catch (e) { return false; }
};
// =======================【崩溃兜底:线程 UncaughtExceptionHandler】=======================
function installCrashHandler(logger) {
@@ -1304,9 +1242,9 @@ function installCrashHandler(logger) {
uncaughtException: function(t, e) {
try {
var tn = "";
try { tn = (t ? String(t.getName()) : ""); } catch (eT) {}
try { tn = (t ? String(t.getName()) : ""); } catch(eT) { safeLog(null, 'e', "catch " + String(eT)); }
var es = "";
try { es = (e ? String(e) : ""); } catch (eE) {}
try { es = (e ? String(e) : ""); } catch(eE) { safeLog(null, 'e', "catch " + String(eE)); }
logger.fatal("UNCAUGHT thread=" + tn + " err=" + es);
try {
var sw = new java.io.StringWriter();
@@ -1314,9 +1252,9 @@ function installCrashHandler(logger) {
e.printStackTrace(pw);
pw.flush();
logger.fatal("STACKTRACE " + String(sw.toString()));
} catch (eST) {}
} catch (e0) {}
try { if (old) old.uncaughtException(t, e); } catch (e1) {}
} catch(eST) { safeLog(null, 'e', "catch " + String(eST)); }
} catch(e0) { safeLog(null, 'e', "catch " + String(e0)); }
try { if (old) old.uncaughtException(t, e); } catch(e1) { safeLog(null, 'e', "catch " + String(e1)); }
}
});
java.lang.Thread.setDefaultUncaughtExceptionHandler(h);

View File

@@ -82,7 +82,7 @@ function FloatBallAppWM(logger) {
this.ui.colors = {};
// # 初始化莫奈动态配色(传入当前主题避免重复检测)
try { this.refreshMonetColors(this.isDarkTheme()); } catch (eM) {}
try { this.refreshMonetColors(this.isDarkTheme()); } catch(eM) { safeLog(null, 'e', "catch " + String(eM)); }
}
// =======================【工具dp/now/clamp】======================
@@ -102,21 +102,21 @@ FloatBallAppWM.prototype.runOnUiThreadSafe = function(fn) {
// 优先使用 Activity 的 runOnUiThread否则使用 View.post
if (this.state && this.state.ballRoot) {
this.state.ballRoot.post(new java.lang.Runnable({
run: function() { try { fn.call(self); } catch(e) {} }
run: function() { try { fn.call(self); } catch(e) { safeLog(null, 'e', "catch " + String(e)); } }
}));
} else {
// 兜底:直接执行(如果已经在 UI 线程)或尝试使用 Handler
try {
var h = new android.os.Handler(android.os.Looper.getMainLooper());
h.post(new java.lang.Runnable({
run: function() { try { fn.call(self); } catch(e) {} }
run: function() { try { fn.call(self); } catch(e) { safeLog(null, 'e', "catch " + String(e)); } }
}));
} catch(e) {
// 最后兜底:直接执行
try { fn.call(self); } catch(e2) {}
try { fn.call(self); } catch(e2) { safeLog(null, 'e', "catch " + String(e2)); }
}
}
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
};
// # 这段代码的主要内容/用途统一图标缓存LRU减少反复解码/反复走 PackageManager降低卡顿与内存波动不改变 UI 与功能)

View File

@@ -44,7 +44,7 @@ FloatBallAppWM.prototype._iconCache = {
var bmp = item.dr.getBitmap();
if (bmp && !bmp.isRecycled()) bmp.recycle();
}
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
delete this.map[key];
}
},
@@ -77,7 +77,7 @@ FloatBallAppWM.prototype._iconLruPut = function(key, val) {
if (ord[i] === k) { ord.splice(i, 1); break; }
}
ord.push(k);
} catch (eLru3) {}
} catch(eLru3) { safeLog(null, 'e', "catch " + String(eLru3)); }
this._iconLru.map[k] = val;
@@ -88,11 +88,11 @@ FloatBallAppWM.prototype._iconLruPut = function(key, val) {
while (ord2.length > maxN) {
var oldK = ord2.shift();
if (oldK != null) {
try { delete this._iconLru.map[oldK]; } catch (eDel) {}
try { delete this._iconLru.map[oldK]; } catch(eDel) { safeLog(null, 'e', "catch " + String(eDel)); }
}
}
} catch (eLru4) {}
} catch (eLru5) {}
} catch(eLru4) { safeLog(null, 'e', "catch " + String(eLru4)); }
} catch(eLru5) { safeLog(null, 'e', "catch " + String(eLru5)); }
};
@@ -112,7 +112,7 @@ FloatBallAppWM.prototype.loadBallIconDrawableFromFile = function(path, targetPx,
ckLru = "file|" + p + "@" + String(targetPx == null ? "" : targetPx) + "@" + String(f.lastModified()) + "@" + String(f.length());
var hitLru = this._iconLruGet(ckLru);
if (hitLru) return hitLru;
} catch (eLruF0) {}
} catch(eLruF0) { safeLog(null, 'e', "catch " + String(eLruF0)); }
// # 文件大小限制(字节)
var limitBytes = Math.max(0, Math.floor(Number(maxBytes || 0)));
@@ -161,7 +161,7 @@ FloatBallAppWM.prototype.loadBallIconDrawableFromFile = function(path, targetPx,
// # 写入统一 LRU 缓存
try {
if (ckLru) this._iconLruPut(ckLru, d);
} catch (eLruF1) {}
} catch(eLruF1) { safeLog(null, 'e', "catch " + String(eLruF1)); }
return d;
} catch (e0) {
return null;

View File

@@ -5,11 +5,11 @@ FloatBallAppWM.prototype.getScreenSizePx = function() {
try { this.state.wm.getDefaultDisplay().getRealMetrics(m); } catch (e) { this.state.wm.getDefaultDisplay().getMetrics(m); }
return { w: m.widthPixels, h: m.heightPixels };
};
FloatBallAppWM.prototype.getRotation = function() { try { return this.state.wm.getDefaultDisplay().getRotation(); } catch (e) {} return -1; };
FloatBallAppWM.prototype.getRotation = function() { try { return this.state.wm.getDefaultDisplay().getRotation(); } catch(e) { safeLog(null, 'e', "catch " + String(e)); } return -1; };
// =======================【工具alpha/toast/vibrate】======================
FloatBallAppWM.prototype.withAlpha = function(colorInt, alpha01) { var a = Math.floor(Number(alpha01) * 255); return (colorInt & 0x00FFFFFF) | (a << 24); };
FloatBallAppWM.prototype.toast = function(msg) { try { android.widget.Toast.makeText(context, String(msg), 0).show(); } catch (e) {} };
FloatBallAppWM.prototype.toast = function(msg) { try { android.widget.Toast.makeText(context, String(msg), 0).show(); } catch(e) { safeLog(null, 'e', "catch " + String(e)); } };
FloatBallAppWM.prototype.vibrateOnce = function(ms) {
if (!this.config.LONG_PRESS_HAPTIC_ENABLE) return;
try {
@@ -22,7 +22,7 @@ FloatBallAppWM.prototype.vibrateOnce = function(ms) {
} else {
vib.vibrate(dur);
}
} catch (e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
};
// =======================【工具UI样式辅助】======================
@@ -133,7 +133,7 @@ FloatBallAppWM.prototype.ui = {
btn.setGravity(android.view.Gravity.CENTER);
var pressedColor = app.withAlpha ? app.withAlpha(bgColor, 0.8) : bgColor;
btn.setBackground(this.createRippleDrawable(bgColor, pressedColor, app.dp(24)));
try { btn.setElevation(app.dp(2)); } catch(e){}
try { btn.setElevation(app.dp(2)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
btn.setOnClickListener(new android.view.View.OnClickListener({
onClick: function(v) { app.touchActivity(); app.guardClick("ui_btn", INTERACTION_CONSTANTS.CLICK_COOLDOWN_MS, function(){ if(onClick) onClick(v); }); }
}));
@@ -154,7 +154,7 @@ FloatBallAppWM.prototype.ui = {
var lb = new android.widget.TextView(context);
lb.setText(label);
lb.setTextColor(this.colors.textSecLight); // 默认用浅色主题副文本色,外部可覆盖
try { if (app.isDarkTheme && app.isDarkTheme()) lb.setTextColor(this.colors.textSecDark); } catch(e){}
try { if (app.isDarkTheme && app.isDarkTheme()) lb.setTextColor(this.colors.textSecDark); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
lb.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 12);
var lpLb = new android.widget.LinearLayout.LayoutParams(0, -2);
lpLb.weight = 1;
@@ -164,14 +164,14 @@ FloatBallAppWM.prototype.ui = {
et.setText(initVal ? String(initVal) : "");
et.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 14);
et.setTextColor(this.colors.textPriLight);
try { if (app.isDarkTheme && app.isDarkTheme()) et.setTextColor(this.colors.textPriDark); } catch(e){}
try { if (app.isDarkTheme && app.isDarkTheme()) et.setTextColor(this.colors.textPriDark); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
// 输入框背景优化
var strokeColor = this.colors.dividerLight;
try { if (app.isDarkTheme && app.isDarkTheme()) strokeColor = this.colors.dividerDark; } catch(e){}
try { if (app.isDarkTheme && app.isDarkTheme()) strokeColor = this.colors.dividerDark; } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
var bg = this.createStrokeDrawable(this.colors.inputBgLight, strokeColor, app.dp(1), app.dp(8));
try { if (app.isDarkTheme && app.isDarkTheme()) bg = this.createStrokeDrawable(this.colors.inputBgDark, strokeColor, app.dp(1), app.dp(8)); } catch(e){}
try { if (app.isDarkTheme && app.isDarkTheme()) bg = this.createStrokeDrawable(this.colors.inputBgDark, strokeColor, app.dp(1), app.dp(8)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
et.setBackground(bg);
et.setPadding(app.dp(8), app.dp(8), app.dp(8), app.dp(8));
@@ -234,10 +234,10 @@ FloatBallAppWM.prototype.ui = {
} else {
errTv.setVisibility(android.view.View.GONE);
var strokeColor = self.colors.dividerLight;
try { if (app.isDarkTheme && app.isDarkTheme()) strokeColor = self.colors.dividerDark; } catch(e){}
try { if (app.isDarkTheme && app.isDarkTheme()) strokeColor = self.colors.dividerDark; } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
var normalBg = self.createStrokeDrawable(self.colors.inputBgLight, strokeColor, app.dp(1), app.dp(8));
try { if (app.isDarkTheme && app.isDarkTheme()) normalBg = self.createStrokeDrawable(self.colors.inputBgDark, strokeColor, app.dp(1), app.dp(8)); } catch(e){}
try { if (app.isDarkTheme && app.isDarkTheme()) normalBg = self.createStrokeDrawable(self.colors.inputBgDark, strokeColor, app.dp(1), app.dp(8)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
et.setBackground(normalBg);
}
}
@@ -256,7 +256,7 @@ FloatBallAppWM.prototype.ui = {
bgDr.setColor(bgColor);
bgDr.setCornerRadius(app.dp(16));
panel.setBackground(bgDr);
try { panel.setElevation(app.dp(8)); } catch(e){}
try { panel.setElevation(app.dp(8)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
var p = (paddingDp !== undefined) ? app.dp(paddingDp) : app.dp(16);
panel.setPadding(p, p, p, p);
@@ -315,7 +315,7 @@ function _th_log(L, level, msg) {
if (level === "w" && L.w) { L.w(msg); return; }
if (level === "i" && L.i) { L.i(msg); return; }
if (L.d) { L.d(msg); return; }
} catch (e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
// =======================【莫奈动态取色工具】======================
@@ -328,7 +328,7 @@ var MonetColorProvider = {
var res = android.content.res.Resources.getSystem();
var id = res.getIdentifier(resName, "color", "android");
if (id > 0) return res.getColor(id, null);
} catch (e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
try { return android.graphics.Color.parseColor(fallbackHex); } catch (e) { return 0; }
},
@@ -418,9 +418,9 @@ var MonetColorProvider = {
try {
var id = res.getIdentifier(map[name], "color", "android");
if (id > 0) c[name] = res.getColor(id, null);
} catch (e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
} catch (e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
return c;
},
@@ -487,14 +487,14 @@ function startActivityAsUserSafe(ctx, intent, userId) {
// 降级到普通启动
try {
ctx.startActivity(intent);
} catch (e2) {}
} catch(e2) { safeLog(null, 'e', "catch " + String(e2)); }
}
}
FloatBallAppWM.prototype.isDarkTheme = function() {
// 0) 优先检查用户强制设置 (0=跟随系统, 1=白天, 2=黑夜)
var mode = 0;
try { mode = Math.floor(Number(this.config.THEME_MODE || 0)); } catch(e){}
try { mode = Math.floor(Number(this.config.THEME_MODE || 0)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
if (mode === 2) return true;
if (mode === 1) return false;
@@ -511,7 +511,7 @@ FloatBallAppWM.prototype.isDarkTheme = function() {
var nightMask = (uiMode & android.content.res.Configuration.UI_MODE_NIGHT_MASK);
if (nightMask === android.content.res.Configuration.UI_MODE_NIGHT_YES) { result = true; from = "Configuration(UI_MODE_NIGHT_YES)"; }
else if (nightMask === android.content.res.Configuration.UI_MODE_NIGHT_NO) { result = false; from = "Configuration(UI_MODE_NIGHT_NO)"; }
} catch (e1) {}
} catch(e1) { safeLog(null, 'e', "catch " + String(e1)); }
if (from === "unknown") {
try {
@@ -523,7 +523,7 @@ FloatBallAppWM.prototype.isDarkTheme = function() {
else if (nm === android.app.UiModeManager.MODE_NIGHT_NO) { result = false; from = "UiModeManager(MODE_NIGHT_NO)"; }
else { from = "UiModeManager(mode=" + String(nm) + ")"; }
}
} catch (e2) {}
} catch(e2) { safeLog(null, 'e', "catch " + String(e2)); }
}
// # 3) 实在判断不了,就按"非暗色"处理,避免自动主题背景黑成一片
@@ -533,14 +533,14 @@ FloatBallAppWM.prototype.isDarkTheme = function() {
var logKey = String(result) + "|" + from + "|" + mode;
if (this._lastDarkThemeLog !== logKey) {
this._lastDarkThemeLog = logKey;
try { _th_log(this.L, "d", "[theme] isDarkTheme=" + String(result) + " via=" + from + " mode=" + mode); } catch (e3) {}
try { _th_log(this.L, "d", "[theme] isDarkTheme=" + String(result) + " via=" + from + " mode=" + mode); } catch(e3) { safeLog(null, 'e', "catch " + String(e3)); }
}
// # 主题切换时刷新莫奈配色(传入 result 避免递归)
// 注:构造函数中会初始化,这里只在构造完成后的切换时触发
if (this._lastDarkResult !== undefined && this._lastDarkResult !== result) {
this._lastDarkResult = result;
try { this.refreshMonetColors(result); } catch (eM) {}
try { this.refreshMonetColors(result); } catch(eM) { safeLog(null, 'e', "catch " + String(eM)); }
} else if (this._lastDarkResult === undefined) {
this._lastDarkResult = result;
}
@@ -592,9 +592,9 @@ FloatBallAppWM.prototype.refreshMonetColors = function(forceDark) {
c._monetSecondary = m.secondary;
c._monetTertiary = m.tertiary;
try { _th_log(this.L, "d", "[monet] refreshed isDark=" + isDark + " primary=" + _th_hex(c.primary) + " primaryDark=" + _th_hex(c.primaryDark) + " accent=" + _th_hex(c.accent)); } catch (e) {}
try { _th_log(this.L, "d", "[monet] refreshed isDark=" + isDark + " primary=" + _th_hex(c.primary) + " primaryDark=" + _th_hex(c.primaryDark) + " accent=" + _th_hex(c.accent)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
} catch (e) {
try { _th_log(this.L, "e", "[monet] refresh err=" + String(e)); } catch (e2) {}
try { _th_log(this.L, "e", "[monet] refresh err=" + String(e)); } catch(e2) { safeLog(null, 'e', "catch " + String(e2)); }
}
};
@@ -618,12 +618,12 @@ FloatBallAppWM.prototype.getMonetAccentForBall = function() {
var logKey = "hit|" + names[i] + "|" + c;
if (this._lastAccentLog !== logKey) {
this._lastAccentLog = logKey;
try { _th_log(this.L, "d", "[theme] hit accent=" + names[i] + " id=" + String(id) + " c=" + _th_hex(c) + " " + _th_argb(c)); } catch (eL0) {}
try { _th_log(this.L, "d", "[theme] hit accent=" + names[i] + " id=" + String(id) + " c=" + _th_hex(c) + " " + _th_argb(c)); } catch(eL0) { safeLog(null, 'e', "catch " + String(eL0)); }
}
return c;
}
} catch (e) {
try { _th_log(this.L, "w", "[theme] err accent=" + names[i] + " e=" + String(e)); } catch (eL2) {}
try { _th_log(this.L, "w", "[theme] err accent=" + names[i] + " e=" + String(e)); } catch(eL2) { safeLog(null, 'e', "catch " + String(eL2)); }
}
}
@@ -634,7 +634,7 @@ FloatBallAppWM.prototype.getMonetAccentForBall = function() {
var logKeyFb = "miss_all|" + fb;
if (this._lastAccentLog !== logKeyFb) {
this._lastAccentLog = logKeyFb;
try { _th_log(this.L, "w", "[theme] accent miss all, fallback=" + _th_hex(fb) + " " + _th_argb(fb)); } catch (eL3) {}
try { _th_log(this.L, "w", "[theme] accent miss all, fallback=" + _th_hex(fb) + " " + _th_argb(fb)); } catch(eL3) { safeLog(null, 'e', "catch " + String(eL3)); }
}
return fb;
};
@@ -649,14 +649,14 @@ FloatBallAppWM.prototype.updateBallContentBackground = function(contentView) {
// # 自定义 PNG/APP 模式下:背景透明
var fillColor = ballColor;
var _usedKind = "none";
try { _usedKind = this.state.usedIconKind || "none"; } catch(eK){}
try { _usedKind = this.state.usedIconKind || "none"; } catch(eK) { safeLog(null, 'e', "catch " + String(eK)); }
try {
var _pngModeBg = Number(this.config.BALL_PNG_MODE || 0);
if ((_pngModeBg === 1 && _usedKind === "file") || _usedKind === "app") {
fillColor = android.graphics.Color.TRANSPARENT;
}
} catch (eBg) {}
} catch(eBg) { safeLog(null, 'e', "catch " + String(eBg)); }
var content = new android.graphics.drawable.GradientDrawable();
content.setShape(android.graphics.drawable.GradientDrawable.OVAL);
@@ -671,7 +671,7 @@ FloatBallAppWM.prototype.updateBallContentBackground = function(contentView) {
? Color.parseColor("#33000000") // 浅球用半透明黑边
: Color.parseColor("#55FFFFFF"); // 深球用半透明白边
content.setStroke(this.dp(1), strokeInt);
} catch(eS){}
} catch(eS) { safeLog(null, 'e', "catch " + String(eS)); }
}
var mask = new android.graphics.drawable.GradientDrawable();
@@ -683,7 +683,7 @@ FloatBallAppWM.prototype.updateBallContentBackground = function(contentView) {
content,
mask
));
} catch (e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
};
@@ -720,7 +720,7 @@ FloatBallAppWM.prototype.getPanelBgColorInt = function() {
var out = this.withAlpha(base, a);
try { _th_log(this.L, "d", "[t]bg isDark=" + isDark + " o=" + _th_hex(out)); } catch (e2) {}
try { _th_log(this.L, "d", "[t]bg isDark=" + isDark + " o=" + _th_hex(out)); } catch(e2) { safeLog(null, 'e', "catch " + String(e2)); }
return out;
};
@@ -757,7 +757,7 @@ FloatBallAppWM.prototype.applyTextColorRecursive = function(v, colorInt) {
this.applyTextColorRecursive(v.getChildAt(i), colorInt);
}
}
} catch (e0) {}
} catch(e0) { safeLog(null, 'e', "catch " + String(e0)); }
};
FloatBallAppWM.prototype.updatePanelBackground = function(panelView) {
@@ -774,15 +774,15 @@ FloatBallAppWM.prototype.updatePanelBackground = function(panelView) {
var isDark = this.isDarkTheme();
var outlineColor = this.ui.colors._monetOutline || (isDark ? android.graphics.Color.parseColor("#8E918F") : android.graphics.Color.parseColor("#747775"));
var stroke = this.withAlpha(outlineColor, isDark ? 0.26 : 0.20);
try { bg.setStroke(sw, stroke); } catch (eS) {}
try { bg.setStroke(sw, stroke); } catch(eS) { safeLog(null, 'e', "catch " + String(eS)); }
panelView.setBackground(bg);
var tc = this.getPanelTextColorInt(bgInt);
try { themeBgInt = bgInt; themeTextInt = tc; } catch (eT) {}
try { themeBgInt = bgInt; themeTextInt = tc; } catch(eT) { safeLog(null, 'e', "catch " + String(eT)); }
this.applyTextColorRecursive(panelView, tc);
try { _th_log(this.L, "d", "[t]apply bg=" + _th_hex(bgInt) + " tx=" + _th_hex(tc)); } catch (e) {}
try { _th_log(this.L, "d", "[t]apply bg=" + _th_hex(bgInt) + " tx=" + _th_hex(tc)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
try {
@@ -792,9 +792,9 @@ FloatBallAppWM.prototype.updatePanelBackground = function(panelView) {
" text=" + _th_hex(tc) + " " + _th_argb(tc) +
" stroke=" + _th_hex(stroke)
);
} catch (eL0) {}
} catch(eL0) { safeLog(null, 'e', "catch " + String(eL0)); }
} catch (e) {
try { _th_log(this.L, "e", "[theme:apply] err=" + String(e)); } catch (eL1) {}
try { _th_log(this.L, "e", "[theme:apply] err=" + String(e)); } catch(eL1) { safeLog(null, 'e', "catch " + String(eL1)); }
}
};

View File

@@ -8,7 +8,7 @@ FloatBallAppWM.prototype.savePanelState = function(key, state) {
// 节流或立即保存? 面板拖动结束通常不频繁,立即保存即可
// 但为了避免连续事件,还是可以复用 savePos 的节流逻辑,或者直接保存
ConfigManager.saveSettings(this.config);
} catch (e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
};
FloatBallAppWM.prototype.loadPanelState = function(key) {
@@ -174,7 +174,7 @@ FloatBallAppWM.prototype._refreshPreviewInternal = function(changedKey) {
// 移除旧面板
if (oldAdded && oldPanel) {
try { this.state.wm.removeView(oldPanel); } catch(e) {}
try { this.state.wm.removeView(oldPanel); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
}
@@ -208,7 +208,7 @@ FloatBallAppWM.prototype.applyImmediateEffectsForKey = function(k) {
this.L.cfg.LOG_ENABLE = !!this.config.LOG_ENABLE;
this.L.i("apply LOG_ENABLE=" + String(this.config.LOG_ENABLE));
}
} catch (eLE) {}
} catch(eLE) { safeLog(null, 'e', "catch " + String(eLE)); }
return;
}
if (k === "LOG_DEBUG") {
@@ -218,7 +218,7 @@ FloatBallAppWM.prototype.applyImmediateEffectsForKey = function(k) {
this.L.cfg.LOG_DEBUG = !!this.config.LOG_DEBUG;
this.L.i("apply LOG_DEBUG=" + String(this.config.LOG_DEBUG));
}
} catch (eLD) {}
} catch(eLD) { safeLog(null, 'e', "catch " + String(eLD)); }
return;
}
if (k === "LOG_KEEP_DAYS") {
@@ -231,7 +231,7 @@ FloatBallAppWM.prototype.applyImmediateEffectsForKey = function(k) {
this.L.i("apply LOG_KEEP_DAYS=" + String(n));
this.L.cleanupOldFiles();
}
} catch (eLK) {}
} catch(eLK) { safeLog(null, 'e', "catch " + String(eLK)); }
return;
}
if (k === "BALL_SIZE_DP" || k === "BALL_PNG_MODE" || k === "BALL_ICON_TYPE" || k === "BALL_ICON_FILE_PATH" || k === "BALL_ICON_RES_ID" || k === "BALL_ICON_RES_NAME" || k === "BALL_ICON_SIZE_DP" || k === "BALL_ICON_TINT_HEX") { this.rebuildBallForNewSize(); return; }
@@ -255,7 +255,7 @@ FloatBallAppWM.prototype.applyImmediateEffectsForKey = function(k) {
}
return;
}
} catch (e0) {}
} catch(e0) { safeLog(null, 'e', "catch " + String(e0)); }
};
FloatBallAppWM.prototype.commitPendingUserCfg = function() {

View File

@@ -51,7 +51,7 @@ FloatBallAppWM.prototype.resolveIconDrawable = function(btn) {
var dr = this.loadBallIconDrawableFromFile(path, this.dp(sizeDp), 1048576, 1024);
if (dr) return dr;
}
} catch (ePath) {}
} catch(ePath) { safeLog(null, 'e', "catch " + String(ePath)); }
}
@@ -74,7 +74,7 @@ try {
}
}
}
} catch (eApp) {}
} catch(eApp) { safeLog(null, 'e', "catch " + String(eApp)); }
// # 1.5) type=shortcut尝试取 Shortcuts 快捷方式图标(显示与 shortcuts.js 页面一致)
@@ -100,13 +100,13 @@ try {
try {
var sk0 = pkg2 + "@" + sid2 + "@" + (btn.userId != null ? String(btn.userId) : "");
this._iconLruPut("sc|" + sk0, dr0);
} catch (eSc0) {}
} catch(eSc0) { safeLog(null, 'e', "catch " + String(eSc0)); }
return dr0;
}
}
} catch(eF0) {}
} catch(eF0) { safeLog(null, 'e', "catch " + String(eF0)); }
}
} catch(eFile0) {}
} catch(eFile0) { safeLog(null, 'e', "catch " + String(eFile0)); }
var skey = pkg2 + "@" + sid2 + "@" + (btn.userId != null ? String(btn.userId) : "");
var kSc = "sc|" + skey;
var hitSc = this._iconLruGet(kSc);
@@ -145,7 +145,7 @@ var skey = pkg2 + "@" + sid2 + "@" + (btn.userId != null ? String(btn.userId) :
var tmpUid2 = parseInt(String(buid2), 10);
if (!isNaN(tmpUid2)) userIdIntForSvc = tmpUid2;
}
} catch(eUidSvc) {}
} catch(eUidSvc) { safeLog(null, 'e', "catch " + String(eUidSvc)); }
var sm2 = android.os.ServiceManager;
var shortcutSvc = null;
@@ -160,23 +160,23 @@ var skey = pkg2 + "@" + sid2 + "@" + (btn.userId != null ? String(btn.userId) :
if (listObj2) list = listObj2;
}
}
} catch(eSvc2) {}
} catch(eSvc2) { safeLog(null, 'e', "catch " + String(eSvc2)); }
// # 2) LauncherApps 回退(当 shortcut service 不可用或返回空时)
if (list == null) {
var q = new android.content.pm.LauncherApps.ShortcutQuery();
try { q.setPackage(pkg2); } catch(eSP) {}
try { q.setPackage(pkg2); } catch(eSP) { safeLog(null, 'e', "catch " + String(eSP)); }
// # 重要:必须设置 QueryFlags否则 getShortcuts 可能返回空(默认 flags=0
// # 兼容性:不同 Android/ROM 可能缺少部分 FLAG逐个 try 叠加
try {
var qFlags = 0;
try { qFlags = qFlags | android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC; } catch(eF1) {}
try { qFlags = qFlags | android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED; } catch(eF2) {}
try { qFlags = qFlags | android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_MANIFEST; } catch(eF3) {}
try { qFlags = qFlags | android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_CACHED; } catch(eF4) {}
try { q.setQueryFlags(qFlags); } catch(eSF) {}
} catch(eQF) {}
try { qFlags = qFlags | android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC; } catch(eF1) { safeLog(null, 'e', "catch " + String(eF1)); }
try { qFlags = qFlags | android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED; } catch(eF2) { safeLog(null, 'e', "catch " + String(eF2)); }
try { qFlags = qFlags | android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_MANIFEST; } catch(eF3) { safeLog(null, 'e', "catch " + String(eF3)); }
try { qFlags = qFlags | android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_CACHED; } catch(eF4) { safeLog(null, 'e', "catch " + String(eF4)); }
try { q.setQueryFlags(qFlags); } catch(eSF) { safeLog(null, 'e', "catch " + String(eSF)); }
} catch(eQF) { safeLog(null, 'e', "catch " + String(eQF)); }
// # 重要:用户句柄优先用按钮携带的 userId如有否则使用当前用户
var uh = android.os.Process.myUserHandle();
@@ -190,7 +190,7 @@ var skey = pkg2 + "@" + sid2 + "@" + (btn.userId != null ? String(btn.userId) :
uh = android.os.UserHandle.of(uidInt);
}
}
} catch(eUH) {}
} catch(eUH) { safeLog(null, 'e', "catch " + String(eUH)); }
try { list = la.getShortcuts(q, uh); } catch(eGS) { list = null; }
}
@@ -219,10 +219,10 @@ if (si != null) {
var d2 = ic.loadDrawable(context);
if (d2 != null) drSc = d2;
}
} catch(eIcon1) {}
} catch(eIcon1) { safeLog(null, 'e', "catch " + String(eIcon1)); }
}
if (drSc != null) {
try { this._iconLruPut("sc|" + skey, drSc); } catch (eSc1) {}
try { this._iconLruPut("sc|" + skey, drSc); } catch(eSc1) { safeLog(null, 'e', "catch " + String(eSc1)); }
return drSc;
}
}
@@ -235,7 +235,7 @@ if (si != null) {
try {
if (nowTs > 0) this._shortcutIconFailTs[skey] = nowTs;
else this._shortcutIconFailTs[skey] = new Date().getTime();
} catch(eFT) {}
} catch(eFT) { safeLog(null, 'e', "catch " + String(eFT)); }
}
@@ -244,10 +244,10 @@ if (si != null) {
var pm2 = context.getPackageManager();
var drApp2 = pm2.getApplicationIcon(pkg2);
if (drApp2 != null) return drApp2;
} catch(eFall) {}
} catch(eFall) { safeLog(null, 'e', "catch " + String(eFall)); }
}
}
} catch (eSc) {}
} catch(eSc) { safeLog(null, 'e', "catch " + String(eSc)); }
// # 2) 显式指定 iconResName (String) 或 iconResId (int)
try {
if (btn.iconResName) {
@@ -259,11 +259,11 @@ if (si != null) {
if (id > 0) return context.getResources().getDrawable(id, null);
}
if (btn.iconResId) return context.getResources().getDrawable(btn.iconResId, null);
} catch (e1) {}
} catch(e1) { safeLog(null, 'e', "catch " + String(e1)); }
// # 3) 兜底
return context.getResources().getDrawable(android.R.drawable.ic_menu_help, null);
} catch (e2) {}
} catch(e2) { safeLog(null, 'e', "catch " + String(e2)); }
return null;
};
@@ -302,7 +302,7 @@ FloatBallAppWM.prototype.normalizeShortXIconName = function(name, keepPrefix) {
return s;
}
return keepPrefix ? ("ic_remix_" + s) : s;
} catch (e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
return "";
};
@@ -320,20 +320,20 @@ FloatBallAppWM.prototype.getShortXApkPaths = function() {
p = String(p || "");
if (!p) return;
if (out.indexOf(p) < 0) out.push(p);
} catch (eP) {}
} catch(eP) { safeLog(null, 'e', "catch " + String(eP)); }
}
if (ai) {
try { pushPath(ai.sourceDir); } catch (e0) {}
try { pushPath(ai.publicSourceDir); } catch (e1) {}
try { pushPath(ai.sourceDir); } catch(e0) { safeLog(null, 'e', "catch " + String(e0)); }
try { pushPath(ai.publicSourceDir); } catch(e1) { safeLog(null, 'e', "catch " + String(e1)); }
try {
var ss = ai.splitSourceDirs;
if (ss) {
var i;
for (i = 0; i < ss.length; i++) pushPath(ss[i]);
}
} catch (e2) {}
} catch(e2) { safeLog(null, 'e', "catch " + String(e2)); }
}
} catch (e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
return out;
};
@@ -371,7 +371,7 @@ FloatBallAppWM.prototype.scanShortXIconsFromApk = function() {
} catch (eZip) {
lastErr = String(eZip);
} finally {
try { if (zip) zip.close(); } catch (eClose) {}
try { if (zip) zip.close(); } catch(eClose) { safeLog(null, 'e', "catch " + String(eClose)); }
}
}
if ((!out || out.length === 0) && lastErr) this._shortxIconCatalogError = "APK扫描: " + lastErr + " (路径数=" + paths.length + ", 文件数=" + totalFiles + ")";
@@ -399,7 +399,7 @@ FloatBallAppWM.prototype.getShortXIconLookupNames = function(name) {
add("ic_remix_" + s);
add("ic_" + s);
}
} catch (e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
return out;
};
@@ -414,7 +414,7 @@ FloatBallAppWM.prototype.resolveShortXDrawableResId = function(name) {
try { resId = handle.res.getIdentifier(String(cands[i]), "drawable", handle.pkg); } catch (e1) { resId = 0; }
if (resId > 0) return resId;
}
} catch (e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
return 0;
};
@@ -429,10 +429,10 @@ FloatBallAppWM.prototype.resolveShortXDrawable = function(name, tintHex) {
try {
dr = dr.mutate();
dr.setColorFilter(android.graphics.Color.parseColor(String(tintHex)), android.graphics.PorterDuff.Mode.SRC_IN);
} catch (eTint) {}
} catch(eTint) { safeLog(null, 'e', "catch " + String(eTint)); }
}
return dr;
} catch (e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
return null;
};
@@ -467,7 +467,7 @@ FloatBallAppWM.prototype.getShortXIconCatalog = function(forceReload) {
shortName: (fname.indexOf("ic_remix_") === 0) ? fname.substring("ic_remix_".length) : fname,
id: f.getInt(null)
});
} catch (eField) {}
} catch(eField) { safeLog(null, 'e', "catch " + String(eField)); }
}
} catch (eClz) {
this._shortxIconCatalogError = "R$drawable reflect: " + String(eClz);

View File

@@ -42,7 +42,7 @@ FloatBallAppWM.prototype.showShortcutPicker = function(opts) {
self.__shortcutPickerSingleton.show(opts);
return;
}
} catch(eSingle) {}
} catch(eSingle) { safeLog(null, 'e', "catch " + String(eSingle)); }
// # 兼容toolhub.js 全局未必定义 Context 别名,这里显式绑定,避免 ReferenceError。
@@ -76,7 +76,7 @@ FloatBallAppWM.prototype.showShortcutPicker = function(opts) {
if (f.exists() && f.isDirectory() && f.canRead()) {
return candidates[i];
}
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
// 反射获取环境变量(最可靠但较慢)
@@ -89,7 +89,7 @@ FloatBallAppWM.prototype.showShortcutPicker = function(opts) {
return envPath;
}
}
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
// 最终兜底
return "/data/system_ce";
@@ -119,7 +119,7 @@ FloatBallAppWM.prototype.showShortcutPicker = function(opts) {
if (!ok) continue;
out.push(parseInt(name, 10));
}
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
// 默认兜底:至少有 user 0
if (out.length === 0) out.push(0);
return out;
@@ -135,7 +135,7 @@ FloatBallAppWM.prototype.showShortcutPicker = function(opts) {
if (typeof getSystemUserDir === "function") {
basePath = getSystemUserDir();
}
} catch(eGSD2) {}
} catch(eGSD2) { safeLog(null, 'e', "catch " + String(eGSD2)); }
var dir = new java.io.File(basePath + "/" + String(userId) + "/shortcut_service/packages");
if (!dir.exists() || !dir.isDirectory()) return out;
@@ -151,7 +151,7 @@ FloatBallAppWM.prototype.showShortcutPicker = function(opts) {
if (pkg && pkg.length > 0) out.push(pkg);
}
}
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
return out;
}
@@ -187,9 +187,9 @@ FloatBallAppWM.prototype.showShortcutPicker = function(opts) {
try {
var s0 = listObj.get(si0);
if (s0) out.push(s0);
} catch(eS2) {}
} catch(eS2) { safeLog(null, 'e', "catch " + String(eS2)); }
}
} catch(eS3) {}
} catch(eS3) { safeLog(null, 'e', "catch " + String(eS3)); }
if (out.length > 0) return out;
}
}
@@ -222,9 +222,9 @@ FloatBallAppWM.prototype.showShortcutPicker = function(opts) {
LauncherAppsShortcutQuery.FLAG_MATCH_PINNED |
LauncherAppsShortcutQuery.FLAG_MATCH_MANIFEST
);
} catch(eF2) {}
} catch(eF2) { safeLog(null, 'e', "catch " + String(eF2)); }
}
try { q.setPackage(safeStr(pkg)); } catch(eP) {}
try { q.setPackage(safeStr(pkg)); } catch(eP) { safeLog(null, 'e', "catch " + String(eP)); }
// user 处理:尽量兼容多用户
var userHandle = null;
@@ -248,9 +248,9 @@ FloatBallAppWM.prototype.showShortcutPicker = function(opts) {
try {
var si = list.get(i);
if (si) out.push(si);
} catch(eI) {}
} catch(eI) { safeLog(null, 'e', "catch " + String(eI)); }
}
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
return out;
}
@@ -261,7 +261,7 @@ FloatBallAppWM.prototype.showShortcutPicker = function(opts) {
var ai = pm.getApplicationInfo(String(pkg), 0);
var lb = pm.getApplicationLabel(ai);
if (lb != null) return String(lb);
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
return String(pkg);
}
@@ -315,14 +315,14 @@ FloatBallAppWM.prototype.showShortcutPicker = function(opts) {
// density: 0 让系统自适应(部分 ROM 更稳)
var dr = la.getShortcutIconDrawable(item.shortcutInfo, 0);
if (dr) return dr;
} catch(eLa) {}
} catch(eLa) { safeLog(null, 'e', "catch " + String(eLa)); }
}
} catch(e0) {}
} catch(e0) { safeLog(null, 'e', "catch " + String(e0)); }
// fallback: app icon
try {
var pm = context.getPackageManager();
return pm.getApplicationIcon(String(item.pkg));
} catch(e1) {}
} catch(e1) { safeLog(null, 'e', "catch " + String(e1)); }
return null;
}
@@ -357,7 +357,7 @@ FloatBallAppWM.prototype.showShortcutPicker = function(opts) {
return ta.localeCompare(tb);
});
order = ["__ALL__"].concat(rest);
} catch(eS) {}
} catch(eS) { safeLog(null, 'e', "catch " + String(eS)); }
return { groups: groups, order: order };
}
@@ -440,13 +440,13 @@ FloatBallAppWM.prototype.showShortcutPicker = function(opts) {
};
function Ld(msg) { try { if (self.L) self.L.d("[shortcut] " + msg); } catch(e) {} }
function Li(msg) { try { if (self.L) self.L.i("[shortcut] " + msg); } catch(e) {} }
function Le(msg) { try { if (self.L) self.L.e("[shortcut] " + msg); } catch(e) {} }
function Ld(msg) { try { if (self.L) self.L.d("[shortcut] " + msg); } catch(e) { safeLog(null, 'e', "catch " + String(e)); } }
function Li(msg) { try { if (self.L) self.L.i("[shortcut] " + msg); } catch(e) { safeLog(null, 'e', "catch " + String(e)); } }
function Le(msg) { try { if (self.L) self.L.e("[shortcut] " + msg); } catch(e) { safeLog(null, 'e', "catch " + String(e)); } }
function runOn(handler, fn) {
try {
handler.post(new JavaAdapter(Runnable, { run: function() { try { fn(); } catch(e) {} } }));
handler.post(new JavaAdapter(Runnable, { run: function() { try { fn(); } catch(e) { safeLog(null, 'e', "catch " + String(e)); } } }));
return true;
} catch(e) { return false; }
}
@@ -462,45 +462,45 @@ FloatBallAppWM.prototype.showShortcutPicker = function(opts) {
state.scrollPollRunning = false;
// # 停止队列与异步:隐藏后不再触发 UI/图标加载逻辑
try { h.removeCallbacksAndMessages(null); } catch(eCB0) {}
try { bgH.removeCallbacksAndMessages(null); } catch(eCB1) {}
try { h.removeCallbacksAndMessages(null); } catch(eCB0) { safeLog(null, 'e', "catch " + String(eCB0)); }
try { bgH.removeCallbacksAndMessages(null); } catch(eCB1) { safeLog(null, 'e', "catch " + String(eCB1)); }
// # 输入法/焦点:无论是否弹出输入法,都先退焦点并尝试隐藏软键盘
try {
if (state.etSearch) {
try { state.etSearch.clearFocus(); } catch(eK0) {}
try { state.etSearch.clearFocus(); } catch(eK0) { safeLog(null, 'e', "catch " + String(eK0)); }
try {
var imm = context.getSystemService(android.content.Context.INPUT_METHOD_SERVICE);
if (imm) imm.hideSoftInputFromWindow(state.etSearch.getWindowToken(), 0);
} catch(eK1) {}
} catch(eK1) { safeLog(null, 'e', "catch " + String(eK1)); }
}
} catch(eK2) {}
} catch(eK2) { safeLog(null, 'e', "catch " + String(eK2)); }
// # 仅隐藏 View不触碰 WM removeView避免 WM/IME token 状态机被打乱
try {
if (state.root) {
state.root.setVisibility(android.view.View.GONE);
}
} catch(eV0) {}
} catch(eV0) { safeLog(null, 'e', "catch " + String(eV0)); }
// # 退出线程hide 时也释放线程,避免反复打开/隐藏导致线程堆积
try {
var killer = new Thread(new JavaAdapter(Runnable, {
run: function() {
try { bgHt.quitSafely(); } catch(e2) {}
try { ht.quitSafely(); } catch(e3) {}
try { bgHt.quitSafely(); } catch(e2) { safeLog(null, 'e', "catch " + String(e2)); }
try { ht.quitSafely(); } catch(e3) { safeLog(null, 'e', "catch " + String(e3)); }
}
}));
killer.start();
} catch(eQuit) {}
} catch(eQuit) { safeLog(null, 'e', "catch " + String(eQuit)); }
// # 通知外层:选择器已隐藏,可恢复上层面板显示
try {
if (state.onDismiss && !state.onDismissCalled) {
state.onDismissCalled = true;
try { state.onDismiss(); } catch(eOD0) {}
try { state.onDismiss(); } catch(eOD0) { safeLog(null, 'e', "catch " + String(eOD0)); }
}
} catch(eOD1) {}
} catch(eOD1) { safeLog(null, 'e', "catch " + String(eOD1)); }
});
}
@@ -516,51 +516,51 @@ FloatBallAppWM.prototype.showShortcutPicker = function(opts) {
state.scrollPollRunning = false;
// # 清理消息队列
try { h.removeCallbacksAndMessages(null); } catch(eCB0) {}
try { bgH.removeCallbacksAndMessages(null); } catch(eCB1) {}
try { h.removeCallbacksAndMessages(null); } catch(eCB0) { safeLog(null, 'e', "catch " + String(eCB0)); }
try { bgH.removeCallbacksAndMessages(null); } catch(eCB1) { safeLog(null, 'e', "catch " + String(eCB1)); }
try { state.iconQ = []; } catch(e0) {}
try { state.iconQ = []; } catch(e0) { safeLog(null, 'e', "catch " + String(e0)); }
state.iconInFlight = 0;
// # 通知外层:选择器即将销毁,可恢复上层面板显示
try {
if (state.onDismiss && !state.onDismissCalled) {
state.onDismissCalled = true;
try { state.onDismiss(); } catch(eOD0) {}
try { state.onDismiss(); } catch(eOD0) { safeLog(null, 'e', "catch " + String(eOD0)); }
}
} catch(eOD1) {}
} catch(eOD1) { safeLog(null, 'e', "catch " + String(eOD1)); }
// # 输入法/焦点清理
try {
if (state.etSearch) {
try { state.etSearch.clearFocus(); } catch(eK0) {}
try { state.etSearch.clearFocus(); } catch(eK0) { safeLog(null, 'e', "catch " + String(eK0)); }
try {
var imm = context.getSystemService(android.content.Context.INPUT_METHOD_SERVICE);
if (imm) imm.hideSoftInputFromWindow(state.etSearch.getWindowToken(), 0);
} catch(eK1) {}
} catch(eK1) { safeLog(null, 'e', "catch " + String(eK1)); }
}
} catch(eK2) {}
} catch(eK2) { safeLog(null, 'e', "catch " + String(eK2)); }
// # 尝试移除 View失败也吞掉避免把 system_server 再次打穿)
var rootRef = state.root;
var wasAdded = state.isAdded;
try {
if (rootRef && wasAdded) {
try { wm.removeViewImmediate(rootRef); } catch(eR0) { try { wm.removeView(rootRef); } catch(eR1) {} }
try { wm.removeViewImmediate(rootRef); } catch(eR0) { try { wm.removeView(rootRef); } catch(eR1) { safeLog(null, 'e', "catch " + String(eR1)); } }
}
} catch(eR2) {}
} catch(eR2) { safeLog(null, 'e', "catch " + String(eR2)); }
state.isAdded = false;
state.root = null;
// # 单例清理
try { if (self.__shortcutPickerSingleton && self.__shortcutPickerSingleton.instanceId === state.instanceId) self.__shortcutPickerSingleton = null; } catch(eS0) {}
try { if (self.__shortcutPickerSingleton && self.__shortcutPickerSingleton.instanceId === state.instanceId) self.__shortcutPickerSingleton = null; } catch(eS0) { safeLog(null, 'e', "catch " + String(eS0)); }
// # 退出线程
var killer = new Thread(new JavaAdapter(Runnable, {
run: function() {
try { bgHt.quitSafely(); } catch(e2) {}
try { ht.quitSafely(); } catch(e3) {}
try { bgHt.quitSafely(); } catch(e2) { safeLog(null, 'e', "catch " + String(e2)); }
try { ht.quitSafely(); } catch(e3) { safeLog(null, 'e', "catch " + String(e3)); }
}
}));
killer.start();
@@ -633,7 +633,7 @@ function cacheGet(key) {
if (state.destroyed) return;
if (dr) {
try { j.iv.setImageDrawable(dr); } catch(e1) {}
try { j.iv.setImageDrawable(dr); } catch(e1) { safeLog(null, 'e', "catch " + String(e1)); }
cachePut(j.key, dr);
} else {
markIconFail(j.key);
@@ -645,7 +645,7 @@ function cacheGet(key) {
}
}
function setStat(text) { try { if (state.tvStat) state.tvStat.setText(String(text)); } catch(e) {} }
function setStat(text) { try { if (state.tvStat) state.tvStat.setText(String(text)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); } }
function rebuildRenderList() {
var g = state.groups ? state.groups[state.currentGroupKey] : null;
@@ -661,7 +661,7 @@ function cacheGet(key) {
function clearGrid() {
try {
if (state.grid) state.grid.removeAllViews();
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
function appendBatch() {
@@ -687,7 +687,7 @@ function cacheGet(key) {
var lpRow = new android.widget.LinearLayout.LayoutParams(android.widget.LinearLayout.LayoutParams.MATCH_PARENT, android.widget.LinearLayout.LayoutParams.WRAP_CONTENT);
lpRow.setMargins(0, 0, 0, self.dp(8));
row.setLayoutParams(lpRow);
} catch(eLpR) {}
} catch(eLpR) { safeLog(null, 'e', "catch " + String(eLpR)); }
row.setPadding(self.dp(12), self.dp(10), self.dp(12), self.dp(10));
@@ -697,18 +697,18 @@ function cacheGet(key) {
var bgColor = isDark ? self.ui.colors.cardDark : self.ui.colors.cardLight;
var stroke = isDark ? self.ui.colors.dividerDark : self.ui.colors.dividerLight;
row.setBackground(self.ui.createStrokeDrawable(bgColor, stroke, self.dp(1), self.dp(12)));
} catch(eBg) {}
} catch(eBg) { safeLog(null, 'e', "catch " + String(eBg)); }
var iv = new android.widget.ImageView(context);
var lpI = new android.widget.LinearLayout.LayoutParams(self.dp(40), self.dp(40));
lpI.setMargins(0, 0, self.dp(12), 0);
iv.setLayoutParams(lpI);
try { iv.setImageResource(android.R.drawable.sym_def_app_icon); } catch(eI0) {}
try { iv.setImageResource(android.R.drawable.sym_def_app_icon); } catch(eI0) { safeLog(null, 'e', "catch " + String(eI0)); }
var key = safeStr(it.pkg) + "@" + safeStr(it.id) + "@" + safeStr(it.userId);
var cached = cacheGet(key);
if (cached) {
try { iv.setImageDrawable(cached); } catch(eIC) {}
try { iv.setImageDrawable(cached); } catch(eIC) { safeLog(null, 'e', "catch " + String(eIC)); }
} else {
enqueueIconLoad(it, iv, key);
}
@@ -722,8 +722,8 @@ function cacheGet(key) {
var tv1 = new android.widget.TextView(context);
tv1.setText(safeStr(it.label || it.id || it.pkg));
tv1.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 14);
try { tv1.setTypeface(null, android.graphics.Typeface.BOLD); } catch(eB) {}
try { tv1.setTextColor(self.isDarkTheme() ? self.ui.colors.textPriDark : self.ui.colors.textPriLight); } catch(eC1) {}
try { tv1.setTypeface(null, android.graphics.Typeface.BOLD); } catch(eB) { safeLog(null, 'e', "catch " + String(eB)); }
try { tv1.setTextColor(self.isDarkTheme() ? self.ui.colors.textPriDark : self.ui.colors.textPriLight); } catch(eC1) { safeLog(null, 'e', "catch " + String(eC1)); }
tv1.setSingleLine(true);
tv1.setEllipsize(android.text.TextUtils.TruncateAt.END);
col.addView(tv1);
@@ -733,7 +733,7 @@ function cacheGet(key) {
tv2.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 11);
tv2.setSingleLine(true);
tv2.setEllipsize(android.text.TextUtils.TruncateAt.END);
try { tv2.setTextColor(self.isDarkTheme() ? self.ui.colors.textSecDark : self.ui.colors.textSecLight); } catch(eC2) {}
try { tv2.setTextColor(self.isDarkTheme() ? self.ui.colors.textSecDark : self.ui.colors.textSecLight); } catch(eC2) { safeLog(null, 'e', "catch " + String(eC2)); }
col.addView(tv2);
// # pick 模式:额外显示 userId避免多用户/工作资料混淆
@@ -742,7 +742,7 @@ function cacheGet(key) {
tv3.setText("userId: " + safeStr(it.userId));
tv3.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 10);
tv3.setSingleLine(true);
try { tv3.setTextColor(self.isDarkTheme() ? self.ui.colors.textSecDark : self.ui.colors.textSecLight); } catch(eC3) {}
try { tv3.setTextColor(self.isDarkTheme() ? self.ui.colors.textSecDark : self.ui.colors.textSecLight); } catch(eC3) { safeLog(null, 'e', "catch " + String(eC3)); }
col.addView(tv3);
}
@@ -771,7 +771,7 @@ function cacheGet(key) {
} catch(eStart) {
self.toast("启动失败: " + eStart);
}
} catch(eClick) {}
} catch(eClick) { safeLog(null, 'e', "catch " + String(eClick)); }
}
}));
@@ -817,7 +817,7 @@ function cacheGet(key) {
tv.setTextColor(isSel ? tPri : tSec);
tv.setBackground(self.ui.createStrokeDrawable(bgColor, stroke, self.dp(1), self.dp(16)));
} catch(eBg) {}
} catch(eBg) { safeLog(null, 'e', "catch " + String(eBg)); }
tv.setOnClickListener(new android.view.View.OnClickListener({
onClick: function() {
@@ -835,7 +835,7 @@ function cacheGet(key) {
state.tabRow.addView(tv);
})(order[i]);
}
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
function startScrollPoll() {
@@ -862,7 +862,7 @@ function cacheGet(key) {
appendBatch();
}
}
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
schedule();
});
}
@@ -870,7 +870,7 @@ function cacheGet(key) {
function schedule() {
try {
h.postDelayed(new JavaAdapter(Runnable, { run: tick }), 180);
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
schedule();
@@ -889,8 +889,8 @@ function cacheGet(key) {
var title = new android.widget.TextView(context);
title.setText(mode === "pick" ? "选择快捷方式" : "快捷方式浏览器");
title.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 16);
try { title.setTypeface(null, android.graphics.Typeface.BOLD); } catch(e) {}
try { title.setTextColor(self.isDarkTheme() ? self.ui.colors.textPriDark : self.ui.colors.textPriLight); } catch(e) {}
try { title.setTypeface(null, android.graphics.Typeface.BOLD); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
try { title.setTextColor(self.isDarkTheme() ? self.ui.colors.textPriDark : self.ui.colors.textPriLight); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
var lpT = new android.widget.LinearLayout.LayoutParams(0, android.widget.LinearLayout.LayoutParams.WRAP_CONTENT);
lpT.weight = 1;
@@ -903,7 +903,7 @@ function cacheGet(key) {
try {
btnClose.setPadding(self.dp(12), self.dp(6), self.dp(12), self.dp(6));
btnClose.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 13);
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
top.addView(title);
top.addView(btnClose);
@@ -916,12 +916,12 @@ function cacheGet(key) {
try {
et.setTextColor(self.isDarkTheme() ? self.ui.colors.textPriDark : self.ui.colors.textPriLight);
et.setHintTextColor(self.isDarkTheme() ? self.ui.colors.textSecDark : self.ui.colors.textSecLight);
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
try {
var inBg = self.ui.createRoundDrawable(self.isDarkTheme() ? self.ui.colors.inputBgDark : self.ui.colors.inputBgLight, self.dp(12));
et.setBackground(inBg);
} catch(eBg) {}
} catch(eBg) { safeLog(null, 'e', "catch " + String(eBg)); }
// # Tabs横向滚动统一为"胶囊按钮"风格,选中态更明确)
var tabSv = new android.widget.HorizontalScrollView(context);
@@ -930,13 +930,13 @@ function cacheGet(key) {
var tabRow = new android.widget.LinearLayout(context);
tabRow.setOrientation(android.widget.LinearLayout.HORIZONTAL);
try { tabRow.setPadding(0, self.dp(8), 0, self.dp(6)); } catch(e) {}
try { tabRow.setPadding(0, self.dp(8), 0, self.dp(6)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
tabSv.addView(tabRow);
// # 状态栏(数量/渲染进度)
var tvStat = new android.widget.TextView(context);
tvStat.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 12);
try { tvStat.setTextColor(self.isDarkTheme() ? self.ui.colors.textSecDark : self.ui.colors.textSecLight); } catch(e) {}
try { tvStat.setTextColor(self.isDarkTheme() ? self.ui.colors.textSecDark : self.ui.colors.textSecLight); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
tvStat.setPadding(0, self.dp(6), 0, self.dp(6));
// # 列表(卡片式条目列表)
@@ -946,7 +946,7 @@ function cacheGet(key) {
var list = new android.widget.LinearLayout(context);
list.setOrientation(android.widget.LinearLayout.VERTICAL);
try { list.setPadding(0, self.dp(2), 0, self.dp(2)); } catch(e) {}
try { list.setPadding(0, self.dp(2), 0, self.dp(2)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
sv.addView(list);
// bind
@@ -970,10 +970,10 @@ function cacheGet(key) {
rebuildRenderList();
clearGrid();
appendBatch();
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
}));
} catch(eTw) {}
} catch(eTw) { safeLog(null, 'e', "catch " + String(eTw)); }
// layout
root.addView(top);
@@ -983,7 +983,7 @@ function cacheGet(key) {
var lpEt = new android.widget.LinearLayout.LayoutParams(android.widget.LinearLayout.LayoutParams.MATCH_PARENT, android.widget.LinearLayout.LayoutParams.WRAP_CONTENT);
lpEt.setMargins(0, 0, 0, self.dp(8));
et.setLayoutParams(lpEt);
} catch(eLpEt) {}
} catch(eLpEt) { safeLog(null, 'e', "catch " + String(eLpEt)); }
root.addView(et);
root.addView(tabSv);
@@ -995,7 +995,7 @@ function cacheGet(key) {
root.addView(sv);
// 主题:用 ToolHub 现有的背景更新逻辑兜底(防止外部主题配置影响)
try { self.updatePanelBackground(root); } catch(eTheme) {}
try { self.updatePanelBackground(root); } catch(eTheme) { safeLog(null, 'e', "catch " + String(eTheme)); }
return root;
}
@@ -1018,19 +1018,19 @@ function cacheGet(key) {
try {
state.params.softInputMode = android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING
| android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN;
} catch(eSIM1) {}
} catch(eSIM1) { safeLog(null, 'e', "catch " + String(eSIM1)); }
try {
state.params.flags = state.params.flags
| android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
} catch(eTop1) {}
} catch(eTop1) { safeLog(null, 'e', "catch " + String(eTop1)); }
var sw2 = (self.state && self.state.screen && self.state.screen.w) ? self.state.screen.w : 0;
if (sw2 > 0) state.params.x = Math.max(0, Math.round((sw2 - state.params.width) / 2));
else state.params.x = 0;
state.params.y = 0;
wm.updateViewLayout(state.root, state.params);
}
} catch(ePos2) {}
} catch(ePos2) { safeLog(null, 'e', "catch " + String(ePos2)); }
// # 层级修复:同类型(TYPE_APPLICATION_OVERLAY)窗口之间的上下层由 addView 顺序决定
// # 说明:当"新增按钮页/主面板"在本窗口之后 addView 时,会把本窗口盖住;复用 show 仅 setVisibility 无法提升层级
@@ -1039,16 +1039,16 @@ function cacheGet(key) {
var tsNow = now();
if (!state.lastRaiseTs || (tsNow - state.lastRaiseTs) > 300) {
state.lastRaiseTs = tsNow;
try { wm.removeViewImmediate(state.root); } catch(eZ0) {}
try { wm.addView(state.root, state.params); } catch(eZ1) {}
try { wm.removeViewImmediate(state.root); } catch(eZ0) { safeLog(null, 'e', "catch " + String(eZ0)); }
try { wm.addView(state.root, state.params); } catch(eZ1) { safeLog(null, 'e', "catch " + String(eZ1)); }
state.isAdded = true;
}
} catch(eZ2) {}
try { state.root.setVisibility(android.view.View.VISIBLE); } catch(eVis) {}
} catch(eZ2) { safeLog(null, 'e', "catch " + String(eZ2)); }
try { state.root.setVisibility(android.view.View.VISIBLE); } catch(eVis) { safeLog(null, 'e', "catch " + String(eVis)); }
try {
setStat("正在加载快捷方式...");
Li("reloading shortcuts index...");
} catch(e0) {}
} catch(e0) { safeLog(null, 'e', "catch " + String(e0)); }
try {
state.allItems = buildShortcutItemsIndex();
var gg = groupItems(state.allItems);
@@ -1060,11 +1060,11 @@ try { state.root.setVisibility(android.view.View.VISIBLE); } catch(eVis) {}
state.groupOrder = ["__ALL__"];
Le("build index err=" + String(e1));
}
try { setupTabs(); } catch(eT0) {}
try { rebuildRenderList(); } catch(eT1) {}
try { clearGrid(); } catch(eT2) {}
try { appendBatch(); } catch(eT3) {}
try { startScrollPoll(); } catch(eT4) {}
try { setupTabs(); } catch(eT0) { safeLog(null, 'e', "catch " + String(eT0)); }
try { rebuildRenderList(); } catch(eT1) { safeLog(null, 'e', "catch " + String(eT1)); }
try { clearGrid(); } catch(eT2) { safeLog(null, 'e', "catch " + String(eT2)); }
try { appendBatch(); } catch(eT3) { safeLog(null, 'e', "catch " + String(eT3)); }
try { startScrollPoll(); } catch(eT4) { safeLog(null, 'e', "catch " + String(eT4)); }
Li("shortcut picker reused items=" + String(state.allItems.length));
return;
}
@@ -1073,7 +1073,7 @@ try { state.root.setVisibility(android.view.View.VISIBLE); } catch(eVis) {}
// build data
setStat("正在加载快捷方式...");
Li("loading shortcuts index...");
} catch(e0) {}
} catch(e0) { safeLog(null, 'e', "catch " + String(e0)); }
try {
state.allItems = buildShortcutItemsIndex();
@@ -1102,13 +1102,13 @@ try { state.root.setVisibility(android.view.View.VISIBLE); } catch(eVis) {}
try {
p.softInputMode = android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING
| android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN;
} catch(eSIM0) {}
} catch(eSIM0) { safeLog(null, 'e', "catch " + String(eSIM0)); }
// # 允许窗口覆盖到屏幕顶部区域(含状态栏区域),避免视觉上"不是贴顶"
try {
p.flags = p.flags
| android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
} catch(eTop0) {}
} catch(eTop0) { safeLog(null, 'e', "catch " + String(eTop0)); }
p.width = self.dp(340);
p.height = self.dp(520);
// # UI 修复:选择快捷方式页应贴近屏幕顶部显示(与"新增按钮页"的顶部布局一致),而不是居中
@@ -1128,7 +1128,7 @@ try { state.root.setVisibility(android.view.View.VISIBLE); } catch(eVis) {}
// 允许输入法:搜索框要能聚焦
try {
p.flags = p.flags & (~android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
} catch(eF) {}
} catch(eF) { safeLog(null, 'e', "catch " + String(eF)); }
state.params = p;
@@ -1161,15 +1161,15 @@ try { state.root.setVisibility(android.view.View.VISIBLE); } catch(eVis) {}
var o = newOpts || {};
mode = (o.mode != null) ? String(o.mode) : mode;
onPick = (typeof o.onPick === "function") ? o.onPick : onPick;
} catch(eOpt) {}
} catch(eOpt) { safeLog(null, 'e', "catch " + String(eOpt)); }
// # 显示前先把隐藏标记清掉
try { state.hidden = false; } catch(eH0) {}
try { state.hidden = false; } catch(eH0) { safeLog(null, 'e', "catch " + String(eH0)); }
show();
},
hide: hide,
destroy: destroy
};
try { self.__shortcutPickerSingleton = api; } catch(eSet) {}
try { self.__shortcutPickerSingleton = api; } catch(eSet) { safeLog(null, 'e', "catch " + String(eSet)); }
api.show(opts);
};
@@ -1196,7 +1196,7 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
self.__iconPickerSingleton.show(opts);
return;
}
} catch(eSingle) {}
} catch(eSingle) { safeLog(null, 'e', "catch " + String(eSingle)); }
// # 获取图标列表
var allIcons = [];
@@ -1207,7 +1207,7 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
}
if (!allIcons || allIcons.length === 0) {
self.toast("无法加载 ShortX 图标库");
if (onDismiss) try { onDismiss(); } catch(eD) {}
if (onDismiss) try { onDismiss(); } catch(eD) { safeLog(null, 'e', "catch " + String(eD)); }
return;
}
@@ -1237,8 +1237,8 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
totalPages: 1
};
function Li(msg) { try { if (self.L) self.L.i("[iconPicker] " + msg); } catch(e) {} }
function Le(msg) { try { if (self.L) self.L.e("[iconPicker] " + msg); } catch(e) {} }
function Li(msg) { try { if (self.L) self.L.i("[iconPicker] " + msg); } catch(e) { safeLog(null, 'e', "catch " + String(e)); } }
function Le(msg) { try { if (self.L) self.L.e("[iconPicker] " + msg); } catch(e) { safeLog(null, 'e', "catch " + String(e)); } }
// # 列数自适应计算
function computeColumns() {
@@ -1292,14 +1292,14 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
// # 过滤
function filterIcons(q) {
var qLower = "";
try { qLower = String(q || "").toLowerCase(); } catch(e) {}
try { qLower = String(q || "").toLowerCase(); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
if (!qLower) return allIcons.slice();
var out = [];
for (var i = 0; i < allIcons.length; i++) {
var ic = allIcons[i];
if (!ic) continue;
var name = "";
try { name = String(ic.shortName || ic.name || "").toLowerCase(); } catch(e) {}
try { name = String(ic.shortName || ic.name || "").toLowerCase(); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
if (name.indexOf(qLower) >= 0) out.push(ic);
}
return out;
@@ -1316,8 +1316,8 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
// 滚回顶部
try {
if (state.scrollView) state.scrollView.scrollTo(0, 0);
} catch(eScroll) {}
} catch(e) {}
} catch(eScroll) { safeLog(null, 'e', "catch " + String(eScroll)); }
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
// # 更新统计/页码显示
@@ -1345,11 +1345,11 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
child.setEnabled(state.currentPage < state.totalPages - 1);
child.setAlpha(state.currentPage < state.totalPages - 1 ? 1.0 : 0.35);
}
} catch(eTag) {}
} catch(eTag) { safeLog(null, 'e', "catch " + String(eTag)); }
}
}
} catch(eBar) {}
} catch(e) {}
} catch(eBar) { safeLog(null, 'e', "catch " + String(eBar)); }
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
// # 构建网格(只渲染当前页)
@@ -1397,8 +1397,8 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
try {
var dr = self.resolveShortXDrawable(iconInfo.name);
if (dr) iv.setImageDrawable(dr);
} catch(eIcon) {}
try { iv.setScaleType(android.widget.ImageView.ScaleType.CENTER_INSIDE); } catch(e) {}
} catch(eIcon) { safeLog(null, 'e', "catch " + String(eIcon)); }
try { iv.setScaleType(android.widget.ImageView.ScaleType.CENTER_INSIDE); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
var ivLp = new android.widget.LinearLayout.LayoutParams(self.dp(cellSizeDp), self.dp(cellSizeDp));
iv.setLayoutParams(ivLp);
cell.addView(iv);
@@ -1406,13 +1406,13 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
// 文字
var tv = new android.widget.TextView(context);
var label = "";
try { label = String(iconInfo.shortName || iconInfo.name || ""); } catch(e) {}
try { label = String(iconInfo.shortName || iconInfo.name || ""); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
if (label.length > 10) label = label.substring(0, 9) + "…";
tv.setText(label);
tv.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, labelSizeSp);
tv.setTextColor(textColor);
tv.setGravity(android.view.Gravity.CENTER);
try { tv.setLines(1); tv.setEllipsize(android.text.TextUtils.TruncateAt.END); } catch(e) {}
try { tv.setLines(1); tv.setEllipsize(android.text.TextUtils.TruncateAt.END); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
var tvLp = new android.widget.LinearLayout.LayoutParams(
android.widget.LinearLayout.LayoutParams.MATCH_PARENT,
android.widget.LinearLayout.LayoutParams.WRAP_CONTENT
@@ -1436,7 +1436,7 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
self.touchActivity();
if (onPick) onPick(iconInfo.name);
hide();
} catch(eClick) {}
} catch(eClick) { safeLog(null, 'e', "catch " + String(eClick)); }
}
}));
@@ -1459,7 +1459,7 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
state.totalPages = Math.max(1, Math.ceil(state.filteredIcons.length / state.itemsPerPage));
state.currentPage = 0;
buildGrid();
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
// # 隐藏
@@ -1475,12 +1475,12 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
var imm = context.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm) imm.hideSoftInputFromWindow(state.etSearch.getWindowToken(), 0);
}
} catch(eK) {}
} catch(eK) { safeLog(null, 'e', "catch " + String(eK)); }
// 隐藏 View
try {
if (state.root) state.root.setVisibility(android.view.View.GONE);
} catch(eV) {}
} catch(eV) { safeLog(null, 'e', "catch " + String(eV)); }
// 通知外层
try {
@@ -1488,10 +1488,10 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
state.onDismissCalled = true;
state.onDismiss();
}
} catch(eD) {}
} catch(eD) { safeLog(null, 'e', "catch " + String(eD)); }
Li("icon picker hidden");
} catch(eHide) {}
} catch(eHide) { safeLog(null, 'e', "catch " + String(eHide)); }
}
// # 销毁
@@ -1507,7 +1507,7 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
if (state.isAdded && state.root) {
wm.removeView(state.root);
}
} catch(eR) {}
} catch(eR) { safeLog(null, 'e', "catch " + String(eR)); }
state.isAdded = false;
state.root = null;
@@ -1515,10 +1515,10 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
if (self.__currentIconSession === currentSession) {
self.__currentIconSession = null;
}
try { self.__iconPickerSingleton = null; } catch(eS) {}
try { self.__iconPickerSingleton = null; } catch(eS) { safeLog(null, 'e', "catch " + String(eS)); }
Li("icon picker destroyed");
} catch(eDes) {}
} catch(eDes) { safeLog(null, 'e', "catch " + String(eDes)); }
}
// # 显示(关键修复:正确处理隐藏后重新显示)
@@ -1550,7 +1550,7 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
// 如果 root 存在但未添加(不应该发生),清掉重建
if (state.root && !state.isAdded) {
try { state.root = null; } catch(e) {}
try { state.root = null; } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
// ========== 新建面板 ==========
@@ -1585,7 +1585,7 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
hide();
}
}
} catch(eOut) {}
} catch(eOut) { safeLog(null, 'e', "catch " + String(eOut)); }
}
return false;
}
@@ -1598,7 +1598,7 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
bgDr.setColor(bgColor);
bgDr.setCornerRadius(self.dp(16));
panel.setBackground(bgDr);
try { panel.setElevation(self.dp(8)); } catch(e) {}
try { panel.setElevation(self.dp(8)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
panel.setPadding(self.dp(16), self.dp(12), self.dp(16), self.dp(12));
var panelLp = new android.widget.FrameLayout.LayoutParams(panelW, android.widget.FrameLayout.LayoutParams.WRAP_CONTENT);
@@ -1656,7 +1656,7 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
var et = new android.widget.EditText(context);
et.setHint("搜索图标名称...");
try { et.setHintTextColor(subTextColor); } catch(e) {}
try { et.setHintTextColor(subTextColor); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
et.setTextColor(textColor);
et.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 14);
et.setBackground(null);
@@ -1671,7 +1671,7 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
try {
state.query = String(s || "");
rebuild();
} catch(eTxt) {}
} catch(eTxt) { safeLog(null, 'e', "catch " + String(eTxt)); }
}
}));
@@ -1689,7 +1689,7 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
et.setText("");
state.query = "";
rebuild();
} catch(eClr) {}
} catch(eClr) { safeLog(null, 'e', "catch " + String(eClr)); }
}
}));
searchBox.addView(btnClear);
@@ -1698,8 +1698,8 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
// --- 滚动区域 ---
var scroll = new android.widget.ScrollView(context);
try { scroll.setOverScrollMode(android.view.View.OVER_SCROLL_NEVER); } catch(e) {}
try { scroll.setVerticalScrollBarEnabled(false); } catch(e) {}
try { scroll.setOverScrollMode(android.view.View.OVER_SCROLL_NEVER); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
try { scroll.setVerticalScrollBarEnabled(false); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
var grid = new android.widget.GridLayout(context);
state.grid = grid;
@@ -1754,11 +1754,11 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
self.dp(6)
);
btn.setBackground(btnBg);
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
btn.setClickable(true);
btn.setOnClickListener(new android.view.View.OnClickListener({
onClick: function() {
try { self.touchActivity(); } catch(e) {}
try { self.touchActivity(); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
onClick();
}
}));
@@ -1806,7 +1806,7 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
} catch(eAdd) {
Le("addView failed: " + String(eAdd));
self.toast("图标选择器打开失败");
if (onDismiss) try { onDismiss(); } catch(eD) {}
if (onDismiss) try { onDismiss(); } catch(eD) { safeLog(null, 'e', "catch " + String(eD)); }
return;
}
@@ -1825,7 +1825,7 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
.setDuration(180)
.setInterpolator(new android.view.animation.AccelerateDecelerateInterpolator())
.start();
} catch(eA) {}
} catch(eA) { safeLog(null, 'e', "catch " + String(eA)); }
// 初始渲染(会计算分页)
rebuild();
@@ -1842,14 +1842,14 @@ FloatBallAppWM.prototype.showIconPicker = function(opts) {
onDismiss = (typeof o.onDismiss === "function") ? o.onDismiss : onDismiss;
state.onDismiss = onDismiss;
state.onDismissCalled = false;
} catch(eOpt) {}
} catch(eOpt) { safeLog(null, 'e', "catch " + String(eOpt)); }
// 不在这里设置 state.hidden = false让内部 show() 自己判断是隐藏重显还是新建
show();
},
hide: hide,
destroy: destroy
};
try { self.__iconPickerSingleton = api; } catch(eSet) {}
try { self.__iconPickerSingleton = api; } catch(eSet) { safeLog(null, 'e', "catch " + String(eSet)); }
api.show(opts);
};

View File

@@ -114,7 +114,7 @@ FloatBallAppWM.prototype.contentQueryToText = function(uriStr, projection, selec
out.err = String(e);
return out;
} finally {
try { if (cur) cur.close(); } catch (eC) {}
try { if (cur) cur.close(); } catch(eC) { safeLog(null, 'e', "catch " + String(eC)); }
}
};

View File

@@ -15,7 +15,7 @@ FloatBallAppWM.prototype.animateBallLayout = function(toX, toY, toW, durMs, endC
// 0.7 的张力适中,不会过于夸张
va.setInterpolator(new android.view.animation.OvershootInterpolator(0.7));
} catch (eI) {
try { va.setInterpolator(new android.view.animation.DecelerateInterpolator()); } catch (eI2) {}
try { va.setInterpolator(new android.view.animation.DecelerateInterpolator()); } catch(eI2) { safeLog(null, 'e', "catch " + String(eI2)); }
}
var self = this;
@@ -41,15 +41,18 @@ FloatBallAppWM.prototype.animateBallLayout = function(toX, toY, toW, durMs, endC
self.state.wm.updateViewLayout(self.state.ballRoot, self.state.ballLp);
}, true, self.L);
}
} catch (e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
}));
va.addListener(new android.animation.Animator.AnimatorListener({
onAnimationStart: function() {},
onAnimationRepeat: function() {},
onAnimationCancel: function() {},
onAnimationCancel: function() {
try { self.state.ballAnimator = null; } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
},
onAnimationEnd: function() {
try { self.state.ballAnimator = null; } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
try {
if (!self.state.closing && self.state.addedBall) {
self.state.ballLp.x = toX;
@@ -58,11 +61,12 @@ FloatBallAppWM.prototype.animateBallLayout = function(toX, toY, toW, durMs, endC
self.state.wm.updateViewLayout(self.state.ballRoot, self.state.ballLp);
self.savePos(self.state.ballLp.x, self.state.ballLp.y);
}
} catch (e2) {}
try { if (endCb) endCb(); } catch (eCb) { try { if (self && self.L && self.L.e) self.L.e("animateBallLayout endCb err=" + String(eCb)); } catch (eLog) {} }
} catch(e2) { safeLog(null, 'e', "catch " + String(e2)); }
try { if (endCb) endCb(); } catch (eCb) { try { if (self && self.L && self.L.e) self.L.e("animateBallLayout endCb err=" + String(eCb)); } catch(eLog) { safeLog(null, 'e', "catch " + String(eLog)); } }
}
}));
this.state.ballAnimator = va;
va.start();
} catch (e0) {
try {
@@ -71,8 +75,8 @@ FloatBallAppWM.prototype.animateBallLayout = function(toX, toY, toW, durMs, endC
st.ballLp.width = toW;
st.wm.updateViewLayout(st.ballRoot, st.ballLp);
this.savePos(st.ballLp.x, st.ballLp.y);
} catch (e1) {}
try { if (endCb) endCb(); } catch (eCb2) { try { if (this && this.L && this.L.e) this.L.e("animateBallLayout endCb err=" + String(eCb2)); } catch (eLog2) {} }
} catch(e1) { safeLog(null, 'e', "catch " + String(e1)); }
try { if (endCb) endCb(); } catch (eCb2) { try { if (this && this.L && this.L.e) this.L.e("animateBallLayout endCb err=" + String(eCb2)); } catch(eLog2) { safeLog(null, 'e', "catch " + String(eLog2)); } }
}
};
@@ -80,7 +84,7 @@ FloatBallAppWM.prototype.playBounce = function(v) {
if (!this.config.ENABLE_BOUNCE) return;
if (!this.config.ENABLE_ANIMATIONS) return;
try { v.animate().cancel(); } catch (e0) {}
try { v.animate().cancel(); } catch(e0) { safeLog(null, 'e', "catch " + String(e0)); }
var self = this;
var i = 0;
@@ -89,7 +93,7 @@ FloatBallAppWM.prototype.playBounce = function(v) {
if (self.state.closing) return;
if (i >= self.config.BOUNCE_TIMES) {
try { v.setScaleX(1); v.setScaleY(1); } catch (e2) {}
try { v.setScaleX(1); v.setScaleY(1); } catch(e2) { safeLog(null, 'e', "catch " + String(e2)); }
return;
}
@@ -202,12 +206,12 @@ FloatBallAppWM.prototype.clearHeavyCaches = function(reason) {
}
this.state[cacheKey] = now;
try { this._iconLru = null; } catch (eLruClr) {}
try { this._shortcutIconFailTs = {}; } catch (e2) {}
try { this._iconLru = null; } catch(eLruClr) { safeLog(null, 'e', "catch " + String(eLruClr)); }
try { this._shortcutIconFailTs = {}; } catch(e2) { safeLog(null, 'e', "catch " + String(e2)); }
// # Shortcuts 相关全局缓存(按钮编辑页/快捷方式选择器可能会创建)
try { if (typeof __scIconCache !== "undefined") __scIconCache = {}; } catch (e3) {}
try { if (typeof __scAppLabelCache !== "undefined") __scAppLabelCache = {}; } catch (e4) {}
try { if (typeof __scIconCache !== "undefined") __scIconCache = {}; } catch(e3) { safeLog(null, 'e', "catch " + String(e3)); }
try { if (typeof __scAppLabelCache !== "undefined") __scAppLabelCache = {}; } catch(e4) { safeLog(null, 'e', "catch " + String(e4)); }
// # 记录一次清理日志(精简:只记录关键 reason且 5秒防抖
var keyReasons = ["memory_pressure", "screen_changed", "close"];
@@ -216,7 +220,7 @@ FloatBallAppWM.prototype.clearHeavyCaches = function(reason) {
if (isKeyReason && this.L && this.L.i) {
this.L.i("clearHeavyCaches reason=" + String(reason));
}
} catch (e5) {}
} catch(e5) { safeLog(null, 'e', "catch " + String(e5)); }
};
FloatBallAppWM.prototype._clearHeavyCachesIfAllHidden = function(reason) {
@@ -225,7 +229,7 @@ FloatBallAppWM.prototype._clearHeavyCachesIfAllHidden = function(reason) {
if (!this.state.addedPanel && !this.state.addedSettings && !this.state.addedViewer) {
this.clearHeavyCaches(reason || "all_hidden");
}
} catch (e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
};
FloatBallAppWM.prototype.hideAllPanels = function() {
@@ -287,7 +291,7 @@ FloatBallAppWM.prototype.showMask = function() {
} else {
mask.setAlpha(1);
}
} catch(eAnim){}
} catch(eAnim) { safeLog(null, 'e', "catch " + String(eAnim)); }
} catch (e1) {
safeLog(this.L, 'e', "add mask fail err=" + String(e1));
@@ -322,7 +326,7 @@ FloatBallAppWM.prototype.snapToEdgeDocked = function(withAnim, forceSide) {
this.state.dockSide = "left";
this.state.docked = true;
try { this.state.ballContent.setX(-hidden); } catch (eL) {}
try { this.state.ballContent.setX(-hidden); } catch(eL) { safeLog(null, 'e', "catch " + String(eL)); }
if (withAnim) {
this.animateBallLayout(0, targetY, targetW, this.config.DOCK_ANIM_MS, null);
@@ -330,7 +334,7 @@ FloatBallAppWM.prototype.snapToEdgeDocked = function(withAnim, forceSide) {
this.state.ballLp.x = 0;
this.state.ballLp.y = targetY;
this.state.ballLp.width = targetW;
try { this.state.wm.updateViewLayout(this.state.ballRoot, this.state.ballLp); } catch (eU1) {}
try { this.state.wm.updateViewLayout(this.state.ballRoot, this.state.ballLp); } catch(eU1) { safeLog(null, 'e', "catch " + String(eU1)); }
this.savePos(this.state.ballLp.x, this.state.ballLp.y);
}
@@ -343,7 +347,7 @@ FloatBallAppWM.prototype.snapToEdgeDocked = function(withAnim, forceSide) {
} else {
this.state.ballContent.setAlpha(this.config.BALL_IDLE_ALPHA);
}
} catch(eA) {}
} catch(eA) { safeLog(null, 'e', "catch " + String(eA)); }
return;
}
@@ -351,7 +355,7 @@ FloatBallAppWM.prototype.snapToEdgeDocked = function(withAnim, forceSide) {
this.state.dockSide = "right";
this.state.docked = true;
try { this.state.ballContent.setX(0); } catch (eR) {}
try { this.state.ballContent.setX(0); } catch(eR) { safeLog(null, 'e', "catch " + String(eR)); }
var x2 = this.state.screen.w - visible;
@@ -361,7 +365,7 @@ FloatBallAppWM.prototype.snapToEdgeDocked = function(withAnim, forceSide) {
this.state.ballLp.x = x2;
this.state.ballLp.y = targetY;
this.state.ballLp.width = targetW;
try { this.state.wm.updateViewLayout(this.state.ballRoot, this.state.ballLp); } catch (eU2) {}
try { this.state.wm.updateViewLayout(this.state.ballRoot, this.state.ballLp); } catch(eU2) { safeLog(null, 'e', "catch " + String(eU2)); }
this.savePos(this.state.ballLp.x, this.state.ballLp.y);
}
@@ -380,7 +384,7 @@ FloatBallAppWM.prototype.snapToEdgeDocked = function(withAnim, forceSide) {
} else {
this.state.ballContent.setAlpha(this.config.BALL_IDLE_ALPHA);
}
} catch(eA) {}
} catch(eA) { safeLog(null, 'e', "catch " + String(eA)); }
};
FloatBallAppWM.prototype.undockToFull = function(withAnim, endCb) {
@@ -393,7 +397,7 @@ FloatBallAppWM.prototype.undockToFull = function(withAnim, endCb) {
var targetW = ballSize;
var targetY = this.clamp(this.state.ballLp.y, 0, this.state.screen.h - ballSize);
try { this.state.ballContent.setX(0); } catch (e0) {}
try { this.state.ballContent.setX(0); } catch(e0) { safeLog(null, 'e', "catch " + String(e0)); }
if (this.state.dockSide === "left") {
this.state.docked = false;
@@ -404,7 +408,7 @@ FloatBallAppWM.prototype.undockToFull = function(withAnim, endCb) {
this.state.ballLp.x = 0;
this.state.ballLp.y = targetY;
this.state.ballLp.width = targetW;
try { this.state.wm.updateViewLayout(this.state.ballRoot, this.state.ballLp); } catch (eU1) {}
try { this.state.wm.updateViewLayout(this.state.ballRoot, this.state.ballLp); } catch(eU1) { safeLog(null, 'e', "catch " + String(eU1)); }
this.savePos(this.state.ballLp.x, this.state.ballLp.y);
if (endCb) endCb();
}
@@ -416,7 +420,7 @@ FloatBallAppWM.prototype.undockToFull = function(withAnim, endCb) {
} else {
this.state.ballContent.setAlpha(1.0);
}
} catch(eA) {}
} catch(eA) { safeLog(null, 'e', "catch " + String(eA)); }
safeLog(this.L, 'i', "undock from left");
return;
@@ -432,7 +436,7 @@ FloatBallAppWM.prototype.undockToFull = function(withAnim, endCb) {
this.state.ballLp.x = x;
this.state.ballLp.y = targetY;
this.state.ballLp.width = targetW;
try { this.state.wm.updateViewLayout(this.state.ballRoot, this.state.ballLp); } catch (eU2) {}
try { this.state.wm.updateViewLayout(this.state.ballRoot, this.state.ballLp); } catch(eU2) { safeLog(null, 'e', "catch " + String(eU2)); }
this.savePos(this.state.ballLp.x, this.state.ballLp.y);
if (endCb) endCb();
}
@@ -444,7 +448,7 @@ FloatBallAppWM.prototype.undockToFull = function(withAnim, endCb) {
} else {
this.state.ballContent.setAlpha(1.0);
}
} catch(eA) {}
} catch(eA) { safeLog(null, 'e', "catch " + String(eA)); }
// # 日志精简undock 事件改为 INFO 级别,且记录方向
var undockSide = this.state.dockSide || "right";
@@ -452,7 +456,7 @@ FloatBallAppWM.prototype.undockToFull = function(withAnim, endCb) {
};
FloatBallAppWM.prototype.cancelDockTimer = function() {
try { if (this.state.idleDockRunnable && this.state.h) this.state.h.removeCallbacks(this.state.idleDockRunnable); } catch (e) {}
try { if (this.state.idleDockRunnable && this.state.h) this.state.h.removeCallbacks(this.state.idleDockRunnable); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
this.state.idleDockRunnable = null;
};
@@ -518,7 +522,7 @@ FloatBallAppWM.prototype.guardClick = function(key, cooldownMs, fn) {
return true;
} catch (e0) {
// 兜底:绝不让点击回调异常冒泡到 system_server
try { fn && fn(); } catch (e2) {}
try { fn && fn(); } catch(e2) { safeLog(null, 'e', "catch " + String(e2)); }
return true;
}
};
@@ -576,22 +580,22 @@ FloatBallAppWM.prototype.onScreenChangedReflow = function() {
if (this.state.dockSide === "left") {
this.state.ballLp.x = 0;
try { this.state.ballContent.setX(-hidden); } catch (eL) {}
try { this.state.ballContent.setX(-hidden); } catch(eL) { safeLog(null, 'e', "catch " + String(eL)); }
} else {
this.state.ballLp.x = newW - visible;
try { this.state.ballContent.setX(0); } catch (eR) {}
try { this.state.ballContent.setX(0); } catch(eR) { safeLog(null, 'e', "catch " + String(eR)); }
}
// 重新进入闲置变暗逻辑(如果需要)
try { this.state.ballContent.setAlpha(this.config.BALL_IDLE_ALPHA); } catch(eA) {}
try { this.state.ballContent.setAlpha(this.config.BALL_IDLE_ALPHA); } catch(eA) { safeLog(null, 'e', "catch " + String(eA)); }
} else {
this.state.ballLp.x = mappedX;
this.state.ballLp.y = mappedY;
this.state.ballLp.width = ballSize;
try { this.state.ballContent.setX(0); } catch (e0) {}
try { this.state.ballContent.setAlpha(1.0); } catch(eA) {}
try { this.state.ballContent.setX(0); } catch(e0) { safeLog(null, 'e', "catch " + String(e0)); }
try { this.state.ballContent.setAlpha(1.0); } catch(eA) { safeLog(null, 'e', "catch " + String(eA)); }
}
try { this.state.wm.updateViewLayout(this.state.ballRoot, this.state.ballLp); } catch (eU) {}
try { this.state.wm.updateViewLayout(this.state.ballRoot, this.state.ballLp); } catch(eU) { safeLog(null, 'e', "catch " + String(eU)); }
this.savePos(this.state.ballLp.x, this.state.ballLp.y);
safeLog(this.L, 'i', "screen reflow w=" + String(newW) + " h=" + String(newH) + " x=" + String(this.state.ballLp.x) + " y=" + String(this.state.ballLp.y));
@@ -642,7 +646,7 @@ FloatBallAppWM.prototype.setupDisplayMonitor = function() {
}
}
}));
} catch (e0) {}
} catch(e0) { safeLog(null, 'e', "catch " + String(e0)); }
}
});
@@ -655,7 +659,7 @@ FloatBallAppWM.prototype.setupDisplayMonitor = function() {
};
FloatBallAppWM.prototype.stopDisplayMonitor = function() {
try { if (this.state.dm && this.state.displayListener) this.state.dm.unregisterDisplayListener(this.state.displayListener); } catch (e) {}
try { if (this.state.dm && this.state.displayListener) this.state.dm.unregisterDisplayListener(this.state.displayListener); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
this.state.displayListener = null;
this.state.dm = null;
};

View File

@@ -37,7 +37,7 @@ FloatBallAppWM.prototype.execButtonAction = function(btn, idx) {
if (lines.length > 1) {
content = lines.reverse().join("\n");
}
} catch(eRev) {}
} catch(eRev) { safeLog(null, 'e', "catch " + String(eRev)); }
this.showViewerPanel("今日日志 (倒序)", content);
return;
@@ -80,7 +80,7 @@ try {
}
} catch (eA) {
// # 兜底:某些 ROM/权限限制下 startActivityAsUser 可能抛异常,回退普通启动
try { context.startActivity(it); } catch (eA2) {}
try { context.startActivity(it); } catch(eA2) { safeLog(null, 'e', "catch " + String(eA2)); }
this.toast("启动失败");
safeLog(this.L, 'e', "start app fail pkg=" + pkg + " uid=" + String(launchUid) + " err=" + String(eA));
}
@@ -98,7 +98,7 @@ return;
try {
var b64x = encodeBase64Utf8(cmdPlain);
if (b64x && b64x.length > 0) cmdB64 = String(b64x);
} catch (eB64a) {}
} catch(eB64a) { safeLog(null, 'e', "catch " + String(eB64a)); }
}
// # 2) cmd_b64 非空但无法解码:把它当作"明文命令"重新编码(保证广播桥/Action 都能吃到正确命令)
@@ -110,13 +110,13 @@ return;
cmdPlain = String(cmdB64);
cmdB64 = "";
}
} catch (eB64b) {}
} catch(eB64b) { safeLog(null, 'e', "catch " + String(eB64b)); }
}
if ((!cmdB64 || cmdB64.length === 0) && cmdPlain && cmdPlain.length > 0) {
try {
var b64y = encodeBase64Utf8(cmdPlain);
if (b64y && b64y.length > 0) cmdB64 = String(b64y);
} catch (eB64c) {}
} catch(eB64c) { safeLog(null, 'e', "catch " + String(eB64c)); }
}
if (!cmdB64 || cmdB64.length === 0) {
@@ -162,7 +162,7 @@ return;
else if (typeof v === "boolean") it2.putExtra(String(k), !!v);
else it2.putExtra(String(k), String(v));
}
} catch (eE) {}
} catch(eE) { safeLog(null, 'e', "catch " + String(eE)); }
}
// # 3) 对"Shell 广播桥"做额外兼容:
@@ -189,7 +189,7 @@ return;
cmdB64 = b64x;
it2.putExtra(kCmdB64, String(cmdB64));
}
} catch (eC2) {}
} catch(eC2) { safeLog(null, 'e', "catch " + String(eC2)); }
}
// # 有 b64 但没明文:也补一份明文(便于外部规则验证;真正执行仍建议用 cmd_b64
@@ -200,7 +200,7 @@ return;
cmdPlain = decoded;
it2.putExtra("cmd", String(cmdPlain));
}
} catch (eC3) {}
} catch(eC3) { safeLog(null, 'e', "catch " + String(eC3)); }
}
// # root广播桥接收端默认以 root 执行,强制传递 true
@@ -211,7 +211,7 @@ return;
} catch (eR0) {
try {
it2.putExtra(kRoot, true);
} catch (eR1) {}
} catch(eR1) { safeLog(null, 'e', "catch " + String(eR1)); }
}
@@ -230,21 +230,21 @@ return;
}
}
}
} catch (eRB) {}
} catch(eRB) { safeLog(null, 'e', "catch " + String(eRB)); }
// # from标识来源便于外部执行器做白名单/审计)
try {
if (!it2.hasExtra(kFrom)) it2.putExtra(kFrom, "ToolHub@system_server");
} catch (eF0) { try { it2.putExtra(kFrom, "ToolHub@system_server"); } catch (eF1) {} }
} catch (eF0) { try { it2.putExtra(kFrom, "ToolHub@system_server"); } catch(eF1) { safeLog(null, 'e', "catch " + String(eF1)); } }
if (this.L) {
try {
this.L.i("broadcast(shell_bridge) action=" + action + " cmd_len=" + String(cmdPlain ? cmdPlain.length : 0) +
" cmd_b64_len=" + String(cmdB64 ? cmdB64.length : 0) + " root=" + String(it2.getBooleanExtra(kRoot, false)));
} catch (eLg) {}
} catch(eLg) { safeLog(null, 'e', "catch " + String(eLg)); }
}
}
} catch (eSB) {}
} catch(eSB) { safeLog(null, 'e', "catch " + String(eSB)); }
try { context.sendBroadcast(it2); } catch (eB) { this.toast("广播失败"); safeLog(this.L, 'e', "broadcast fail action=" + action + " err=" + String(eB)); }
return;
@@ -271,7 +271,7 @@ return;
var lu0 = parseInt(String(btn.launchUserId), 10);
if (!isNaN(lu0)) uid = lu0;
}
} catch(eLu0) {}
} catch(eLu0) { safeLog(null, 'e', "catch " + String(eLu0)); }
if (!spkg) { this.toast("按钮#" + idx + " 缺少 pkg"); return; }
if (!sid) { this.toast("按钮#" + idx + " 缺少 shortcutId"); return; }
@@ -312,7 +312,7 @@ return;
this.toast("未知 type=" + t);
safeLog(this.L, 'w', "unknown btn type=" + t);
} catch (eBtn) {
try { this.toast("按钮执行异常"); } catch (e0) {}
try { this.toast("按钮执行异常"); } catch(e0) { safeLog(null, 'e', "catch " + String(e0)); }
safeLog(this.L, 'e', "execButtonAction crash idx=" + String(idx) + " err=" + String(eBtn));
}

View File

@@ -63,7 +63,7 @@ FloatBallAppWM.prototype.rebuildBallForNewSize = function(keepPanels) {
this.state.ballLp = lp;
this.state.addedBall = true;
} catch (eAdd) {
try { this.toast("重建悬浮球失败: " + String(eAdd)); } catch (eT) {}
try { this.toast("重建悬浮球失败: " + String(eAdd)); } catch(eT) { safeLog(null, 'e', "catch " + String(eT)); }
safeLog(this.L, 'e', "rebuildBall add fail err=" + String(eAdd));
return false;
}

View File

@@ -48,7 +48,7 @@ FloatBallAppWM.prototype.createSettingItemView = function(item, parent, needDivi
var outValue = new android.util.TypedValue();
context.getTheme().resolveAttribute(android.R.attr.selectableItemBackground, outValue, true);
row.setBackgroundResource(outValue.resourceId);
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
row.setPadding(padH, padV, padH, padV);
@@ -70,7 +70,7 @@ FloatBallAppWM.prototype.createSettingItemView = function(item, parent, needDivi
row.addView(tv);
var sw = new android.widget.Switch(context);
try { sw.setTextOn(""); sw.setTextOff(""); } catch (eT) {}
try { sw.setTextOn(""); sw.setTextOff(""); } catch(eT) { safeLog(null, 'e', "catch " + String(eT)); }
// 优化开关颜色
try {
@@ -86,7 +86,7 @@ FloatBallAppWM.prototype.createSettingItemView = function(item, parent, needDivi
sw.setThumbTintList(thumbList);
sw.setTrackTintList(trackList);
} catch(eColor) {}
} catch(eColor) { safeLog(null, 'e', "catch " + String(eColor)); }
var cur = !!self.getPendingValue(item.key);
sw.setChecked(cur);
@@ -98,7 +98,7 @@ FloatBallAppWM.prototype.createSettingItemView = function(item, parent, needDivi
self.touchActivity();
self.setPendingValue(item.key, !!checked);
if (self.L) self.L.d("pending " + String(item.key) + "=" + String(!!checked));
} catch (e0) {}
} catch(e0) { safeLog(null, 'e', "catch " + String(e0)); }
}
}));
@@ -154,7 +154,7 @@ FloatBallAppWM.prototype.createSettingItemView = function(item, parent, needDivi
try {
sb.getThumb().setTint(primary);
sb.getProgressDrawable().setTint(primary);
} catch(eColor) {}
} catch(eColor) { safeLog(null, 'e', "catch " + String(eColor)); }
// 配置 SeekBar
var min = (item.min !== undefined) ? Number(item.min) : 0;
@@ -197,10 +197,10 @@ FloatBallAppWM.prototype.createSettingItemView = function(item, parent, needDivi
if (fromUser) {
self.setPendingValue(item.key, v);
}
} catch (e1) {}
} catch(e1) { safeLog(null, 'e', "catch " + String(e1)); }
},
onStartTrackingTouch: function() { try { self.touchActivity(); } catch (e2) {} },
onStopTrackingTouch: function() { try { self.touchActivity(); } catch (e3) {} }
onStartTrackingTouch: function() { try { self.touchActivity(); } catch(e2) { safeLog(null, 'e', "catch " + String(e2)); } },
onStopTrackingTouch: function() { try { self.touchActivity(); } catch(e3) { safeLog(null, 'e', "catch " + String(e3)); } }
}));
row.addView(sb);
@@ -239,7 +239,7 @@ FloatBallAppWM.prototype.createSettingItemView = function(item, parent, needDivi
if (item.action === "open_btn_mgr") {
self.showPanelAvoidBall("btn_editor");
}
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
}));
row.addView(btn);
@@ -252,7 +252,7 @@ FloatBallAppWM.prototype.createSettingItemView = function(item, parent, needDivi
if (item.action === "open_btn_mgr") {
self.showPanelAvoidBall("btn_editor");
}
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
}));
@@ -289,7 +289,7 @@ FloatBallAppWM.prototype.createSettingItemView = function(item, parent, needDivi
v.requestFocus();
var imm = context.getSystemService(android.content.Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(v, 0);
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
}));
@@ -300,7 +300,7 @@ FloatBallAppWM.prototype.createSettingItemView = function(item, parent, needDivi
try {
self.touchActivity();
self.setPendingValue(item.key, String(s));
} catch (e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
}));
@@ -338,7 +338,7 @@ FloatBallAppWM.prototype.createSettingItemView = function(item, parent, needDivi
var states = [[android.R.attr.state_checked], [-android.R.attr.state_checked]];
var colors = [primary, secColor];
rb.setButtonTintList(new android.content.res.ColorStateList(states, colors));
} catch(eC){}
} catch(eC) { safeLog(null, 'e', "catch " + String(eC)); }
rb.setId(android.view.View.generateViewId ? android.view.View.generateViewId() : i);
@@ -353,7 +353,7 @@ FloatBallAppWM.prototype.createSettingItemView = function(item, parent, needDivi
try {
self.touchActivity();
self.setPendingValue(item.key, String(opt.value));
} catch(e){}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
}
}));
@@ -403,7 +403,7 @@ FloatBallAppWM.prototype.createSettingItemView = function(item, parent, needDivi
} else {
previewIv.setImageDrawable(null);
}
} catch(ePreview0) {}
} catch(ePreview0) { safeLog(null, 'e', "catch " + String(ePreview0)); }
}
refreshBallShortXPreview();
@@ -435,7 +435,7 @@ FloatBallAppWM.prototype.createSettingItemView = function(item, parent, needDivi
try {
self.setPendingValue(item.key, "");
refreshBallShortXPreview();
} catch(eClearBallIcon) {}
} catch(eClearBallIcon) { safeLog(null, 'e', "catch " + String(eClearBallIcon)); }
});
iconRow.addView(btnClear);
row.addView(iconRow);
@@ -478,7 +478,7 @@ FloatBallAppWM.prototype.createSettingItemView = function(item, parent, needDivi
colorDot.setBackground(self.ui.createRoundDrawable(0xFFCCCCCC | 0, self.dp(14)));
}
} catch(eDot0) {
try { colorDot.setBackground(self.ui.createRoundDrawable(0xFFCCCCCC | 0, self.dp(14))); } catch(eDot1) {}
try { colorDot.setBackground(self.ui.createRoundDrawable(0xFFCCCCCC | 0, self.dp(14))); } catch(eDot1) { safeLog(null, 'e', "catch " + String(eDot1)); }
colorValueTv.setText("默认");
}
}
@@ -510,7 +510,7 @@ FloatBallAppWM.prototype.createSettingItemView = function(item, parent, needDivi
try {
self.setPendingValue(item.key, "");
refreshBallColorPreview();
} catch(eClearBallColor) {}
} catch(eClearBallColor) { safeLog(null, 'e', "catch " + String(eClearBallColor)); }
});
colorRow.addView(btnClearColor);
row.addView(colorRow);

File diff suppressed because it is too large Load Diff

View File

@@ -16,7 +16,7 @@ FloatBallAppWM.prototype.buildViewerPanelView = function(titleText, bodyText) {
bgDr.setColor(bgColor);
bgDr.setCornerRadius(this.dp(16));
panel.setBackground(bgDr);
try { panel.setElevation(this.dp(8)); } catch(e){}
try { panel.setElevation(this.dp(8)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
panel.setPadding(
this.dp(16),
@@ -39,8 +39,8 @@ FloatBallAppWM.prototype.buildViewerPanelView = function(titleText, bodyText) {
panel.addView(sep);
var scroll = new android.widget.ScrollView(context);
try { scroll.setOverScrollMode(android.view.View.OVER_SCROLL_NEVER); } catch (eOS) {}
try { scroll.setVerticalScrollBarEnabled(true); } catch (eSB) {}
try { scroll.setOverScrollMode(android.view.View.OVER_SCROLL_NEVER); } catch(eOS) { safeLog(null, 'e', "catch " + String(eOS)); }
try { scroll.setVerticalScrollBarEnabled(true); } catch(eSB) { safeLog(null, 'e', "catch " + String(eSB)); }
// 给内容加一点边距
var contentBox = new android.widget.LinearLayout(context);
@@ -53,11 +53,11 @@ FloatBallAppWM.prototype.buildViewerPanelView = function(titleText, bodyText) {
tv.setTextColor(codeColor);
tv.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, Number(this.config.CONTENT_VIEWER_TEXT_SP || 12));
// 增加行距优化阅读
try { tv.setLineSpacing(this.dp(4), 1.0); } catch(eLS) {}
try { tv.setLineSpacing(this.dp(4), 1.0); } catch(eLS) { safeLog(null, 'e', "catch " + String(eLS)); }
// 使用等宽字体显示代码/日志
try { tv.setTypeface(android.graphics.Typeface.MONOSPACE); } catch(eTF) {}
try { tv.setTypeface(android.graphics.Typeface.MONOSPACE); } catch(eTF) { safeLog(null, 'e', "catch " + String(eTF)); }
// WindowManager 环境下禁用文本选择,否则长按/选择会因缺少 Token 崩溃
try { tv.setTextIsSelectable(false); } catch (eSel) {}
try { tv.setTextIsSelectable(false); } catch(eSel) { safeLog(null, 'e', "catch " + String(eSel)); }
contentBox.addView(tv);
@@ -96,7 +96,7 @@ FloatBallAppWM.prototype.buildPanelView = function(panelType) {
bgDr.setColor(this.withAlpha(bgColor, this.config.PANEL_BG_ALPHA));
bgDr.setCornerRadius(this.dp(16));
panel.setBackground(bgDr);
try { panel.setElevation(this.dp(8)); } catch(e){}
try { panel.setElevation(this.dp(8)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
var padDp = this.config.PANEL_PADDING_DP;
panel.setPadding(
@@ -149,9 +149,9 @@ FloatBallAppWM.prototype.buildPanelView = function(panelType) {
}
var scroll = new android.widget.ScrollView(context);
try { scroll.setOverScrollMode(android.view.View.OVER_SCROLL_NEVER); } catch (eOS) {}
try { scroll.setVerticalScrollBarEnabled(false); } catch (eSB) {}
try { scroll.setFillViewport(true); } catch (eFV) {}
try { scroll.setOverScrollMode(android.view.View.OVER_SCROLL_NEVER); } catch(eOS) { safeLog(null, 'e', "catch " + String(eOS)); }
try { scroll.setVerticalScrollBarEnabled(false); } catch(eSB) { safeLog(null, 'e', "catch " + String(eSB)); }
try { scroll.setFillViewport(true); } catch(eFV) { safeLog(null, 'e', "catch " + String(eFV)); }
var scrollLp = new android.widget.LinearLayout.LayoutParams(contentW, scrollH);
scroll.setLayoutParams(scrollLp);
@@ -170,7 +170,7 @@ FloatBallAppWM.prototype.buildPanelView = function(panelType) {
// var totalCells = totalBtns > minCells ? totalBtns : minCells;
var rowCount = Math.ceil(totalCells / cols2);
try { grid.setRowCount(rowCount); } catch (eRC) {}
try { grid.setRowCount(rowCount); } catch(eRC) { safeLog(null, 'e', "catch " + String(eRC)); }
grid.setOnTouchListener(new JavaAdapter(android.view.View.OnTouchListener, {
onTouch: function(v, e) { self.touchActivity(); return false; }
@@ -193,7 +193,7 @@ FloatBallAppWM.prototype.buildPanelView = function(panelType) {
// 单元格背景:如果是有功能的按钮,给个卡片背景;否则透明
if (btnCfg) {
cell.setBackground(self.ui.createRoundDrawable(cardColor, self.dp(12)));
try { cell.setElevation(self.dp(2)); } catch(e){}
try { cell.setElevation(self.dp(2)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
} else {
// 空格子占位
}
@@ -206,7 +206,7 @@ FloatBallAppWM.prototype.buildPanelView = function(panelType) {
// 但 resolveIconDrawable 逻辑比较复杂,这里暂时不强制染色,除非用户配置了 TINT
if (!isDark && btnCfg && !btnCfg.type && !btnCfg.pkg) {
// 简单的系统图标在亮色模式下可能看不清,染成深色
try { iv.setColorFilter(C.textPriLight, android.graphics.PorterDuff.Mode.SRC_IN); } catch(eCF){}
try { iv.setColorFilter(C.textPriLight, android.graphics.PorterDuff.Mode.SRC_IN); } catch(eCF) { safeLog(null, 'e', "catch " + String(eCF)); }
}
}
@@ -224,7 +224,7 @@ FloatBallAppWM.prototype.buildPanelView = function(panelType) {
tv.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, this.config.PANEL_LABEL_TEXT_SIZE_SP);
tv.setTextColor(textColor);
tv.setGravity(android.view.Gravity.CENTER);
try { tv.setLines(1); tv.setEllipsize(android.text.TextUtils.TruncateAt.END); } catch(eL){}
try { tv.setLines(1); tv.setEllipsize(android.text.TextUtils.TruncateAt.END); } catch(eL) { safeLog(null, 'e', "catch " + String(eL)); }
var tvLp = new android.widget.LinearLayout.LayoutParams(
android.widget.LinearLayout.LayoutParams.MATCH_PARENT, // 宽度填满,方便居中
@@ -251,8 +251,8 @@ FloatBallAppWM.prototype.buildPanelView = function(panelType) {
}));
})(i, btnCfg);
} else {
try { iv.setAlpha(0); } catch (eA0) {}
try { cell.setClickable(false); } catch (eC0) {}
try { iv.setAlpha(0); } catch(eA0) { safeLog(null, 'e', "catch " + String(eA0)); }
try { cell.setClickable(false); } catch(eC0) { safeLog(null, 'e', "catch " + String(eC0)); }
}
grid.addView(cell);
@@ -460,7 +460,7 @@ FloatBallAppWM.prototype.addPanel = function(panel, x, y, which) {
panel.setScaleY(1);
panel.setAlpha(1);
}
} catch (eA) {}
} catch(eA) { safeLog(null, 'e', "catch " + String(eA)); }
// # 日志防抖5秒内相同面板类型不重复记录
var now = Date.now();
@@ -516,8 +516,8 @@ FloatBallAppWM.prototype.showPanelAvoidBall = function(which) {
// 需要处理 newPanel 的 LayoutParams
var contentLp = new android.widget.LinearLayout.LayoutParams(-1, 0);
contentLp.weight = 1;
try { newPanel.setBackground(null); } catch(e){} // 移除背景,使用 Container 背景
try { newPanel.setElevation(0); } catch(e){}
try { newPanel.setBackground(null); } catch(e) { safeLog(null, 'e', "catch " + String(e)); } // 移除背景,使用 Container 背景
try { newPanel.setElevation(0); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
newPanel.setLayoutParams(contentLp);
container.addView(newPanel);
@@ -651,7 +651,7 @@ FloatBallAppWM.prototype.showPanelAvoidBall = function(which) {
self.touchActivity();
} catch (e) {
if (self.L) self.L.e("showPanelAvoidBall callback err=" + String(e));
try { self.toast("面板显示失败: " + String(e)); } catch (et) {}
try { self.toast("面板显示失败: " + String(e)); } catch(et) { safeLog(null, 'e', "catch " + String(et)); }
}
};
@@ -691,7 +691,7 @@ FloatBallAppWM.prototype.wrapDraggablePanel = function(contentView, optionsOrTit
bgDr.setColor(isDark ? C.bgDark : C.bgLight);
bgDr.setCornerRadius(this.dp(12));
container.setBackground(bgDr);
try { container.setElevation(this.dp(8)); } catch(e){}
try { container.setElevation(this.dp(8)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
// Header
var header = new android.widget.LinearLayout(context);
@@ -717,7 +717,7 @@ FloatBallAppWM.prototype.wrapDraggablePanel = function(contentView, optionsOrTit
else self.hideAllPanels();
});
btnClose.setPadding(self.dp(8), self.dp(4), self.dp(8), self.dp(4));
try { btnClose.setElevation(this.dp(25)); } catch(e){} // Ensure on top of resize handles
try { btnClose.setElevation(this.dp(25)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); } // Ensure on top of resize handles
header.addView(btnClose);
// Spacer to avoid overlap with Top-Right resize handle
@@ -733,8 +733,8 @@ FloatBallAppWM.prototype.wrapDraggablePanel = function(contentView, optionsOrTit
// Add Content
// 移除 content 原有的背景和 elevation避免重复
try { contentView.setBackground(null); } catch(e){}
try { contentView.setElevation(0); } catch(e){}
try { contentView.setBackground(null); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
try { contentView.setElevation(0); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
var contentLp = new android.widget.LinearLayout.LayoutParams(-1, 0);
contentLp.weight = 1;
@@ -746,7 +746,7 @@ FloatBallAppWM.prototype.wrapDraggablePanel = function(contentView, optionsOrTit
// Resize Handle (Bottom-Right Corner) - Invisible
var handleBR = new android.view.View(context);
try { handleBR.setElevation(this.dp(20)); } catch(e){}
try { handleBR.setElevation(this.dp(20)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
var handleBRLp = new android.widget.FrameLayout.LayoutParams(this.dp(30), this.dp(30));
handleBRLp.gravity = android.view.Gravity.BOTTOM | android.view.Gravity.END;
handleBRLp.rightMargin = 0;
@@ -755,7 +755,7 @@ FloatBallAppWM.prototype.wrapDraggablePanel = function(contentView, optionsOrTit
// Resize Handle (Bottom-Left Corner) - Invisible
var handleBL = new android.view.View(context);
try { handleBL.setElevation(this.dp(20)); } catch(e){}
try { handleBL.setElevation(this.dp(20)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
var handleBLLp = new android.widget.FrameLayout.LayoutParams(this.dp(30), this.dp(30));
handleBLLp.gravity = android.view.Gravity.BOTTOM | android.view.Gravity.START;
handleBLLp.bottomMargin = 0;
@@ -764,7 +764,7 @@ FloatBallAppWM.prototype.wrapDraggablePanel = function(contentView, optionsOrTit
// Resize Handle (Top-Left Corner) - Invisible
var handleTL = new android.view.View(context);
try { handleTL.setElevation(this.dp(20)); } catch(e){}
try { handleTL.setElevation(this.dp(20)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
var handleTLLp = new android.widget.FrameLayout.LayoutParams(this.dp(30), this.dp(30));
handleTLLp.gravity = android.view.Gravity.TOP | android.view.Gravity.START;
handleTLLp.topMargin = 0;
@@ -773,7 +773,7 @@ FloatBallAppWM.prototype.wrapDraggablePanel = function(contentView, optionsOrTit
// Resize Handle (Top-Right Corner) - Invisible
var handleTR = new android.view.View(context);
try { handleTR.setElevation(this.dp(20)); } catch(e){}
try { handleTR.setElevation(this.dp(20)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
var handleTRLp = new android.widget.FrameLayout.LayoutParams(this.dp(30), this.dp(30));
handleTRLp.gravity = android.view.Gravity.TOP | android.view.Gravity.END;
handleTRLp.topMargin = 0;
@@ -867,7 +867,7 @@ FloatBallAppWM.prototype.attachDragResizeListeners = function(rootView, headerVi
lp.x = targetX;
lp.y = targetY;
try { wm.updateViewLayout(rootView, lp); } catch(e){}
try { wm.updateViewLayout(rootView, lp); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
}
return true;
@@ -938,10 +938,10 @@ FloatBallAppWM.prototype.attachDragResizeListeners = function(rootView, headerVi
lpCur.height = initialH;
lpCur.x = initialX;
lpCur.y = initialY;
try { wm.updateViewLayout(rootView, lpCur); } catch(e){}
try { wm.updateViewLayout(rootView, lpCur); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
resizing = true;
} catch(e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
});
self.state.h.postDelayed(longPressRunnable, 300); // 300ms hold to activate resize
@@ -1022,7 +1022,7 @@ FloatBallAppWM.prototype.attachDragResizeListeners = function(rootView, headerVi
lp.y = Math.round(newY);
}
try { wm.updateViewLayout(rootView, lp); } catch(e){}
try { wm.updateViewLayout(rootView, lp); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
}
return true;
@@ -1138,7 +1138,7 @@ FloatBallAppWM.prototype.showViewerPanel = function(title, text) {
};
FloatBallAppWM.prototype.cancelLongPressTimer = function() {
try { if (this.state.longPressRunnable && this.state.h) this.state.h.removeCallbacks(this.state.longPressRunnable); } catch (e) {}
try { if (this.state.longPressRunnable && this.state.h) this.state.h.removeCallbacks(this.state.longPressRunnable); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
this.state.longPressArmed = false;
this.state.longPressRunnable = null;
};
@@ -1208,7 +1208,7 @@ FloatBallAppWM.prototype.setupTouchListener = function() {
self.touchActivity();
// 恢复不透明度
try { v.setAlpha(1.0); } catch(eA) {}
try { v.setAlpha(1.0); } catch(eA) { safeLog(null, 'e', "catch " + String(eA)); }
if (self.state.docked) {
self.undockToFull(false, null);
@@ -1224,14 +1224,14 @@ FloatBallAppWM.prototype.setupTouchListener = function() {
lastTouchX = e.getRawX();
lastTouchY = e.getRawY();
try { v.setPressed(true); } catch (eP) {}
try { v.drawableHotspotChanged(e.getX(), e.getY()); } catch (eH) {}
try { v.setPressed(true); } catch(eP) { safeLog(null, 'e', "catch " + String(eP)); }
try { v.drawableHotspotChanged(e.getX(), e.getY()); } catch(eH) { safeLog(null, 'e', "catch " + String(eH)); }
// 按下缩小反馈
if (self.config.ENABLE_ANIMATIONS) {
try {
v.animate().scaleX(0.9).scaleY(0.9).setDuration(100).start();
} catch(eS){}
} catch(eS) { safeLog(null, 'e', "catch " + String(eS)); }
}
self.armLongPress();
@@ -1268,11 +1268,11 @@ FloatBallAppWM.prototype.setupTouchListener = function() {
self.state.ballLp.y = self.clamp(self.state.ballLp.y, 0, self.state.screen.h - di.ballSize);
self.state.ballLp.width = di.ballSize;
try { self.state.ballContent.setX(0); } catch (e0) {}
try { self.state.ballContent.setX(0); } catch(e0) { safeLog(null, 'e', "catch " + String(e0)); }
var now = java.lang.System.currentTimeMillis();
if (now - lastUpdateTs > 10) { // 10ms 节流
try { self.state.wm.updateViewLayout(self.state.ballRoot, self.state.ballLp); } catch (eU) {}
try { self.state.wm.updateViewLayout(self.state.ballRoot, self.state.ballLp); } catch(eU) { safeLog(null, 'e', "catch " + String(eU)); }
lastUpdateTs = now;
}
@@ -1286,16 +1286,16 @@ FloatBallAppWM.prototype.setupTouchListener = function() {
if (a === android.view.MotionEvent.ACTION_UP || a === android.view.MotionEvent.ACTION_CANCEL) {
self.touchActivity();
try { v.setPressed(false); } catch (eP2) {}
try { v.setPressed(false); } catch(eP2) { safeLog(null, 'e', "catch " + String(eP2)); }
self.cancelLongPressTimer();
// 恢复缩放
if (self.config.ENABLE_ANIMATIONS) {
try {
v.animate().scaleX(1.0).scaleY(1.0).setDuration(150).start();
} catch(eS){}
} catch(eS) { safeLog(null, 'e', "catch " + String(eS)); }
} else {
try { v.setScaleX(1); v.setScaleY(1); } catch(eS){}
try { v.setScaleX(1); v.setScaleY(1); } catch(eS) { safeLog(null, 'e', "catch " + String(eS)); }
}
if (self.state.longPressTriggered) {
@@ -1305,7 +1305,7 @@ FloatBallAppWM.prototype.setupTouchListener = function() {
}
if (!self.state.dragging && a === android.view.MotionEvent.ACTION_UP) {
try { self.playBounce(v); } catch (eB) {}
try { self.playBounce(v); } catch(eB) { safeLog(null, 'e', "catch " + String(eB)); }
if (self.state.addedPanel) self.hideMainPanel();
else self.showPanelAvoidBall("main");
@@ -1315,7 +1315,7 @@ FloatBallAppWM.prototype.setupTouchListener = function() {
} else {
// 拖拽结束
// 确保最后位置被更新
try { self.state.wm.updateViewLayout(self.state.ballRoot, self.state.ballLp); } catch (eU) {}
try { self.state.wm.updateViewLayout(self.state.ballRoot, self.state.ballLp); } catch(eU) { safeLog(null, 'e', "catch " + String(eU)); }
var forceSide = null;
// 计算速度
@@ -1360,7 +1360,7 @@ FloatBallAppWM.prototype.createBallViews = function() {
var root = new android.widget.FrameLayout(context);
root.setClipToPadding(true);
root.setClipChildren(true);
try { root.setElevation(this.dp(6)); } catch(e){}
try { root.setElevation(this.dp(6)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
var content = new android.widget.FrameLayout(context);
var lp = new android.widget.FrameLayout.LayoutParams(di.ballSize, di.ballSize);
@@ -1419,7 +1419,7 @@ try {
} else {
safeLog(this.L, 'w', "Ball icon file load failed: " + iconFilePath);
}
} catch (eF) {}
} catch(eF) { safeLog(null, 'e', "catch " + String(eF)); }
}
// # 2) app加载应用图标 (file 失败也会尝试 app)
@@ -1434,7 +1434,7 @@ try {
usedKind = "app";
}
}
} catch (eA) {}
} catch(eA) { safeLog(null, 'e', "catch " + String(eA)); }
}
// # 2.5) shortx专门加载 ShortX 内置图标(也作为 file 模式的兜底)
@@ -1455,7 +1455,7 @@ try {
safeLog(this.L, 'i', "File icon failed, fallback to shortx icon");
}
}
} catch (eShortx2) {}
} catch(eShortx2) { safeLog(null, 'e', "catch " + String(eShortx2)); }
}
// # 3) android或所有兜底走资源 id优先尝试 ShortX 内置图标)
@@ -1469,13 +1469,13 @@ try {
if (usedDrawable != null) {
usedKind = "shortx";
}
} catch (eShortx) {}
} catch(eShortx) { safeLog(null, 'e', "catch " + String(eShortx)); }
}
if (usedDrawable != null) {
iv.setImageDrawable(usedDrawable);
} else if (iconResId > 0) {
try { iv.setImageResource(iconResId); usedKind = "android"; } catch (eR) {}
try { iv.setImageResource(iconResId); usedKind = "android"; } catch(eR) { safeLog(null, 'e', "catch " + String(eR)); }
} else {
// # 没有任何可用图标,直接不加到布局
usedKind = "none";
@@ -1505,11 +1505,11 @@ try {
try {
var tintColor2 = android.graphics.Color.parseColor(tintHex);
iv.setColorFilter(tintColor2, android.graphics.PorterDuff.Mode.SRC_IN);
} catch (eTint2) {}
} catch(eTint2) { safeLog(null, 'e', "catch " + String(eTint2)); }
} else if (usedKind === "android") {
try { iv.setColorFilter(android.graphics.Color.WHITE, android.graphics.PorterDuff.Mode.SRC_IN); } catch (eCF) {}
try { iv.setColorFilter(android.graphics.Color.WHITE, android.graphics.PorterDuff.Mode.SRC_IN); } catch(eCF) { safeLog(null, 'e', "catch " + String(eCF)); }
} else {
try { iv.clearColorFilter(); } catch (eCL) {}
try { iv.clearColorFilter(); } catch(eCL) { safeLog(null, 'e', "catch " + String(eCL)); }
}
box.addView(iv);
@@ -1518,7 +1518,7 @@ try {
content.addView(box);
}
} catch (eBallInner) {}
} catch(eBallInner) { safeLog(null, 'e', "catch " + String(eBallInner)); }
this.updateBallContentBackground(content);
@@ -1526,7 +1526,7 @@ try {
// # 阴影控制file/app 模式下不加阴影(避免透明背景带黑框)
var _uk = this.state.usedIconKind;
if (_uk !== "file" && _uk !== "app") {
try { root.setElevation(this.dp(6)); } catch(e){}
try { root.setElevation(this.dp(6)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
}
content.setClickable(true);

View File

@@ -7,7 +7,7 @@ function runOnMainSync(fn, timeoutMs) {
if (mainLooper !== null && myLooper !== null && myLooper === mainLooper) {
return { ok: true, value: fn() };
}
} catch (eLoop) {}
} catch(eLoop) { safeLog(null, 'e', "catch " + String(eLoop)); }
try {
var box = { ok: false, value: null, error: null };
@@ -76,9 +76,17 @@ FloatBallAppWM.prototype.close = function() {
this.cancelDockTimer();
this.stopDisplayMonitor();
// # 取消正在进行的球体动画
try {
if (this.state.ballAnimator) {
this.state.ballAnimator.cancel();
this.state.ballAnimator = null;
}
} catch(eAnim) { safeLog(null, 'e', "catch " + String(eAnim)); }
try {
if (this.state.addedBall && this.state.ballLp) this.savePos(this.state.ballLp.x, this.state.ballLp.y);
} catch (eS) {}
} catch(eS) { safeLog(null, 'e', "catch " + String(eS)); }
try { FileIO.flushDebouncedWrites(); } catch (eFlushCfg) { safeLog(this.L, 'e', "flushDebouncedWrites fail: " + String(eFlushCfg)); }
this.hideAllPanels();
@@ -109,7 +117,7 @@ FloatBallAppWM.prototype.close = function() {
if (android.os.Build.VERSION.SDK_INT >= 18) this.state.ht.quitSafely();
else this.state.ht.quit();
}
} catch (eQ) {}
} catch(eQ) { safeLog(null, 'e', "catch " + String(eQ)); }
// # 清理图标加载线程
try {
@@ -117,14 +125,14 @@ FloatBallAppWM.prototype.close = function() {
if (android.os.Build.VERSION.SDK_INT >= 18) this._iconLoader.ht.quitSafely();
else this._iconLoader.ht.quit();
}
} catch (eIcon) {}
} catch(eIcon) { safeLog(null, 'e', "catch " + String(eIcon)); }
try {
if (self.__scIconLoaderSingleton && self.__scIconLoaderSingleton.ht) {
if (android.os.Build.VERSION.SDK_INT >= 18) self.__scIconLoaderSingleton.ht.quitSafely();
else self.__scIconLoaderSingleton.ht.quit();
}
} catch (eScIcon) {}
try { self.__scIconLoaderSingleton = null; } catch (eScIcon2) {}
} catch(eScIcon) { safeLog(null, 'e', "catch " + String(eScIcon)); }
try { self.__scIconLoaderSingleton = null; } catch(eScIcon2) { safeLog(null, 'e', "catch " + String(eScIcon2)); }
safeLog(this.L, 'i', "close done");
@@ -137,7 +145,7 @@ FloatBallAppWM.prototype.close = function() {
this.L._flushTimer = null;
}
}
} catch (eLog) {}
} catch(eLog) { safeLog(null, 'e', "catch " + String(eLog)); }
// # 清空缓存
try {
@@ -145,7 +153,7 @@ FloatBallAppWM.prototype.close = function() {
this._shortcutIconFailTs = {};
if (typeof __scIconCache !== "undefined") __scIconCache = {};
if (typeof __scAppLabelCache !== "undefined") __scAppLabelCache = {};
} catch (eCache) {}
} catch(eCache) { safeLog(null, 'e', "catch " + String(eCache)); }
};
/**
@@ -161,7 +169,7 @@ FloatBallAppWM.prototype.dispose = function() {
if (self.__shortcutPickerSingleton === this.__shortcutPickerSingleton) {
self.__shortcutPickerSingleton = null;
}
} catch (e) {}
} catch(e) { safeLog(null, 'e', "catch " + String(e)); }
// # 清理配置缓存
this._settingsCache = null;
@@ -196,7 +204,17 @@ FloatBallAppWM.prototype.startAsync = function(entryProcInfo, closeRule) {
shell("am broadcast -a " + String(this.config.ACTION_CLOSE_ALL));
preCloseSent = true;
}
} catch (e1) {}
} catch(e1) { safeLog(null, 'e', "catch " + String(e1)); }
}
// # 清理旧的 HandlerThread防止重复启动导致线程泄漏
if (this.state.ht) {
try {
if (android.os.Build.VERSION.SDK_INT >= 18) this.state.ht.quitSafely();
else this.state.ht.quit();
} catch(eOldHt) { safeLog(null, 'e', "catch " + String(eOldHt)); }
this.state.ht = null;
this.state.h = null;
}
var ht = new android.os.HandlerThread(String(this.config.WM_THREAD_NAME));
@@ -211,9 +229,9 @@ FloatBallAppWM.prototype.startAsync = function(entryProcInfo, closeRule) {
var closeRcv = registerReceiverOnMain(this.config.ACTION_CLOSE_ALL, function(ctx, it) {
try {
h.post(new JavaAdapter(java.lang.Runnable, {
run: function() { try { self.close(); } catch (e1) {} }
run: function() { try { self.close(); } catch(e1) { safeLog(null, 'e', "catch " + String(e1)); } }
}));
} catch (e2) {}
} catch(e2) { safeLog(null, 'e', "catch " + String(e2)); }
});
if (closeRcv) this.state.receivers.push(closeRcv);
@@ -237,10 +255,10 @@ FloatBallAppWM.prototype.startAsync = function(entryProcInfo, closeRule) {
if (self.state.panel) self.updatePanelBackground(self.state.panel);
if (self.state.settingsPanel) self.updatePanelBackground(self.state.settingsPanel);
if (self.state.viewerPanel) self.updatePanelBackground(self.state.viewerPanel);
} catch (e1) {}
} catch(e1) { safeLog(null, 'e', "catch " + String(e1)); }
}
}));
} catch (e0) {}
} catch(e0) { safeLog(null, 'e', "catch " + String(e0)); }
}
);
if (cfgRcv) this.state.receivers.push(cfgRcv);
@@ -265,10 +283,10 @@ FloatBallAppWM.prototype.startAsync = function(entryProcInfo, closeRule) {
self.state.wm.addView(self.state.ballRoot, self.state.ballLp);
self.state.addedBall = true;
} catch (eAdd) {
try { self.toast("悬浮球 addView 失败: " + String(eAdd)); } catch (eT) {}
try { self.toast("悬浮球 addView 失败: " + String(eAdd)); } catch(eT) { safeLog(null, 'e', "catch " + String(eT)); }
if (self.L) self.L.fatal("addView ball fail err=" + String(eAdd));
self.state.addedBall = false;
try { self.close(); } catch (eC) {}
try { self.close(); } catch(eC) { safeLog(null, 'e', "catch " + String(eC)); }
return;
}
@@ -280,9 +298,9 @@ FloatBallAppWM.prototype.startAsync = function(entryProcInfo, closeRule) {
self.L.i("ball x=" + String(self.state.ballLp.x) + " y=" + String(self.state.ballLp.y) + " sizeDp=" + String(self.config.BALL_SIZE_DP));
}
} catch (eAll) {
try { self.toast("启动异常: " + String(eAll)); } catch (eTT2) {}
try { self.toast("启动异常: " + String(eAll)); } catch(eTT2) { safeLog(null, 'e', "catch " + String(eTT2)); }
if (self.L) self.L.fatal("start runnable err=" + String(eAll));
try { self.close(); } catch (eC2) {}
try { self.close(); } catch(eC2) { safeLog(null, 'e', "catch " + String(eC2)); }
}
}
}));