- Split th_2_core.js (4715 lines, 177KB) into: th_02_core.js, th_03_icon.js, th_04_theme.js, th_05_persistence.js, th_06_icon_parser.js, th_07_shortcut.js, th_08_content.js, th_09_animation.js, th_10_shell.js, th_11_action.js, th_12_rebuild.js, th_13_panel_ui.js - Rename existing: th_1_base→th_01_base, th_3_panels→th_14_panels, th_4_extra→th_15_extra, th_5_entry→th_16_entry - Update ToolHub.js MODULE_MANIFEST, modules array, and critical module check
210 lines
7.7 KiB
JavaScript
210 lines
7.7 KiB
JavaScript
// @version 1.0.0
|
||
// =======================【Content:解析 settings URI】======================
|
||
// 这段代码的主要内容/用途:识别 content://settings/(system|secure|global)/KEY 并用 Settings.* get/put 更稳
|
||
FloatBallAppWM.prototype.parseSettingsUri = function(uriStr) {
|
||
try {
|
||
var s = String(uriStr || "");
|
||
if (s.indexOf("content://settings/") !== 0) return null;
|
||
|
||
// content://settings/system/accelerometer_rotation
|
||
var rest = s.substring("content://settings/".length);
|
||
var parts = rest.split("/");
|
||
if (!parts || parts.length < 1) return null;
|
||
|
||
var table = String(parts[0] || "");
|
||
var key = "";
|
||
if (parts.length >= 2) key = String(parts[1] || "");
|
||
|
||
if (table !== "system" && table !== "secure" && table !== "global") return null;
|
||
return { table: table, key: key };
|
||
} catch (e) { return null; }
|
||
};
|
||
|
||
FloatBallAppWM.prototype.settingsGetStringByTable = function(table, key) {
|
||
try {
|
||
var cr = context.getContentResolver();
|
||
if (table === "system") return android.provider.Settings.System.getString(cr, String(key));
|
||
if (table === "secure") return android.provider.Settings.Secure.getString(cr, String(key));
|
||
if (table === "global") return android.provider.Settings.Global.getString(cr, String(key));
|
||
return null;
|
||
} catch (e) { return null; }
|
||
};
|
||
|
||
FloatBallAppWM.prototype.settingsPutStringByTable = function(table, key, value) {
|
||
try {
|
||
var cr = context.getContentResolver();
|
||
if (table === "system") return android.provider.Settings.System.putString(cr, String(key), String(value));
|
||
if (table === "secure") return android.provider.Settings.Secure.putString(cr, String(key), String(value));
|
||
if (table === "global") return android.provider.Settings.Global.putString(cr, String(key), String(value));
|
||
return false;
|
||
} catch (e) { return false; }
|
||
};
|
||
|
||
// =======================【Content:通用 query】======================
|
||
// 这段代码的主要内容/用途:ContentResolver.query 并把 Cursor 转成文本(用于查看器面板)
|
||
FloatBallAppWM.prototype.contentQueryToText = function(uriStr, projection, selection, selectionArgs, sortOrder, maxRows) {
|
||
var out = { ok: false, uri: String(uriStr || ""), rows: 0, text: "", err: "" };
|
||
var cr = null;
|
||
var cur = null;
|
||
|
||
try {
|
||
cr = context.getContentResolver();
|
||
var uri = android.net.Uri.parse(String(uriStr));
|
||
|
||
var projArr = null;
|
||
if (projection && projection.length) {
|
||
projArr = java.lang.reflect.Array.newInstance(java.lang.String, projection.length);
|
||
var i0;
|
||
for (i0 = 0; i0 < projection.length; i0++) projArr[i0] = String(projection[i0]);
|
||
}
|
||
|
||
var sel = (selection === undefined || selection === null) ? null : String(selection);
|
||
|
||
var selArgsArr = null;
|
||
if (selectionArgs && selectionArgs.length) {
|
||
selArgsArr = java.lang.reflect.Array.newInstance(java.lang.String, selectionArgs.length);
|
||
var i1;
|
||
for (i1 = 0; i1 < selectionArgs.length; i1++) selArgsArr[i1] = String(selectionArgs[i1]);
|
||
}
|
||
|
||
var so = (sortOrder === undefined || sortOrder === null) ? null : String(sortOrder);
|
||
|
||
cur = cr.query(uri, projArr, sel, selArgsArr, so);
|
||
if (!cur) {
|
||
out.err = "query return null cursor";
|
||
return out;
|
||
}
|
||
|
||
var colCount = cur.getColumnCount();
|
||
var cols = [];
|
||
var ci;
|
||
for (ci = 0; ci < colCount; ci++) cols.push(String(cur.getColumnName(ci)));
|
||
|
||
var sb = [];
|
||
sb.push("URI: " + String(uriStr));
|
||
sb.push("Columns(" + String(colCount) + "): " + cols.join(", "));
|
||
sb.push("");
|
||
|
||
var limit = Math.max(1, Math.floor(Number(maxRows || this.config.CONTENT_MAX_ROWS || 20)));
|
||
var row = 0;
|
||
|
||
while (cur.moveToNext()) {
|
||
row++;
|
||
sb.push("#" + String(row));
|
||
var cj;
|
||
for (cj = 0; cj < colCount; cj++) {
|
||
var v = "";
|
||
try {
|
||
if (cur.isNull(cj)) v = "null";
|
||
else v = String(cur.getString(cj));
|
||
} catch (eV) {
|
||
try { v = String(cur.getLong(cj)); } catch (eV2) { v = "<??>"; }
|
||
}
|
||
sb.push(" " + cols[cj] + " = " + v);
|
||
}
|
||
sb.push("");
|
||
if (row >= limit) break;
|
||
}
|
||
|
||
out.ok = true;
|
||
out.rows = row;
|
||
out.text = sb.join("\n");
|
||
return out;
|
||
} catch (e) {
|
||
out.err = String(e);
|
||
return out;
|
||
} finally {
|
||
try { if (cur) cur.close(); } catch (eC) {}
|
||
}
|
||
};
|
||
|
||
// =======================【Content:统一入口】======================
|
||
// 这段代码的主要内容/用途:处理按钮里的 type:"content"
|
||
FloatBallAppWM.prototype.execContentAction = function(btn) {
|
||
var mode = btn.mode ? String(btn.mode) : ((btn.value !== undefined && btn.value !== null) ? "put" : "get");
|
||
var uri = btn.uri ? String(btn.uri) : "";
|
||
if (!uri) return { ok: false, err: "missing uri" };
|
||
|
||
// settings uri 优先走 Settings API
|
||
var su = this.parseSettingsUri(uri);
|
||
|
||
if (mode === "get") {
|
||
if (su && su.key) {
|
||
var v = this.settingsGetStringByTable(su.table, su.key);
|
||
return { ok: true, mode: "get", kind: "settings", table: su.table, key: su.key, value: (v === null ? "null" : String(v)) };
|
||
}
|
||
|
||
// 非 settings:尝试 query 一行
|
||
var q1 = this.contentQueryToText(uri, btn.projection, btn.selection, btn.selectionArgs, btn.sortOrder, 1);
|
||
if (!q1.ok) return { ok: false, mode: "get", kind: "query", err: q1.err };
|
||
return { ok: true, mode: "get", kind: "query", text: q1.text, rows: q1.rows };
|
||
}
|
||
|
||
if (mode === "put") {
|
||
var val = (btn.value === undefined || btn.value === null) ? "" : String(btn.value);
|
||
|
||
if (su && su.key) {
|
||
var ok = this.settingsPutStringByTable(su.table, su.key, val);
|
||
return { ok: !!ok, mode: "put", kind: "settings", table: su.table, key: su.key, value: val };
|
||
}
|
||
|
||
// 非 settings:尽力走 update(ContentValues)
|
||
try {
|
||
var cr = context.getContentResolver();
|
||
var u = android.net.Uri.parse(uri);
|
||
var cv = new android.content.ContentValues();
|
||
|
||
// 支持 btn.values = {col1: "...", col2: "..."};否则写 value 列
|
||
if (btn.values) {
|
||
var k;
|
||
for (k in btn.values) {
|
||
if (!btn.values.hasOwnProperty(k)) continue;
|
||
cv.put(String(k), String(btn.values[k]));
|
||
}
|
||
} else {
|
||
cv.put("value", val);
|
||
}
|
||
|
||
var where = (btn.selection === undefined || btn.selection === null) ? null : String(btn.selection);
|
||
|
||
var whereArgs = null;
|
||
if (btn.selectionArgs && btn.selectionArgs.length) {
|
||
whereArgs = java.lang.reflect.Array.newInstance(java.lang.String, btn.selectionArgs.length);
|
||
var i2;
|
||
for (i2 = 0; i2 < btn.selectionArgs.length; i2++) whereArgs[i2] = String(btn.selectionArgs[i2]);
|
||
}
|
||
|
||
var n = cr.update(u, cv, where, whereArgs);
|
||
return { ok: true, mode: "put", kind: "update", updated: Number(n) };
|
||
} catch (eU) {
|
||
return { ok: false, mode: "put", kind: "update", err: String(eU) };
|
||
}
|
||
}
|
||
|
||
if (mode === "query") {
|
||
var maxRows = (btn.maxRows === undefined || btn.maxRows === null) ? this.config.CONTENT_MAX_ROWS : Number(btn.maxRows);
|
||
var q = this.contentQueryToText(uri, btn.projection, btn.selection, btn.selectionArgs, btn.sortOrder, maxRows);
|
||
if (!q.ok) return { ok: false, mode: "query", err: q.err };
|
||
return { ok: true, mode: "query", rows: q.rows, text: q.text };
|
||
}
|
||
|
||
if (mode === "view") {
|
||
try {
|
||
var it = new android.content.Intent(android.content.Intent.ACTION_VIEW);
|
||
it.setData(android.net.Uri.parse(uri));
|
||
it.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
|
||
context.startActivity(it);
|
||
return { ok: true, mode: "view" };
|
||
} catch (eV) {
|
||
return { ok: false, mode: "view", err: String(eV) };
|
||
}
|
||
}
|
||
|
||
return { ok: false, err: "unknown mode=" + mode };
|
||
};
|
||
|
||
/* =======================
|
||
下面开始:WM 动画、面板、触摸、启动、输出
|
||
======================= */
|
||
|