索尼CBO
2023-05-31 一加7 Pro
墓碑模式使用 FCM 推送 v2.1 版本
重要提示:
需要将 Thanox 更新到 v4.1.9 或更高版本,否则情景模式无法正常运行。
更新内容:
1. 优化获取应用列表的逻辑 (依赖 Thanox v4.1.9 新增的 Pkg.newPkg 方法);
2. 重新添加上一版移除的应用是否处于前台的判断逻辑;
3. 新增收到推送时尝试启动未运行应用的逻辑。
使用说明:
1. 仅适配了 FreezerV2(uid) 控制器,如使用其他控制器,请自行修改;
2. 测试环境是 Android13 + NoActive@2.9-Alpha + Thnox@4.2.1-row,理论上兼容其他墓碑模块,请自行测试。
如果能够访问 GitHub 的话,请访问这个链接查看:
查看链接
情景模式:
[
{
"name": "墓碑模式FCM推送v2.1",
"description": "!!!Thanox需要更新到v4.1.9或更高版本!!!\n对于支持FCM推送的应用,当其收到推送并且处于后台时,唤醒它5秒。\n仅适配了FreezerV2(uid)控制器,使用NoActive测试正常,理论上与各墓碑模块兼容。",
"priority": -1,
"condition": "fcmPushMessageArrived == true",
"actions": [
"def debug(msg) { log.log(\"🚀 \" + msg); } def getUserIdList() { userList = context.getSystemService(context.USER_SERVICE).getUsers(); userIdList = (identifier in (userHandle in userList)); return userIdList; } def getPkgByNameAndUserId(pkgName, userId) { pkg = Pkg.newPkg(pkgName, userId); return pkg; } def isValidPkg(pkg) { return thanos.getPkgManager().getAppInfo(pkg) != null; } def getPkgListByPkgName(pkgName) { userIdList = getUserIdList(); res = []; foreach(userId: userIdList) { pkg = getPkgByNameAndUserId(pkgName, userId); if (isValidPkg(pkg)) { res.add(pkg); } } return res; } def getProcessListByPkgList(pkgList) { processList = []; foreach(pkg : pkgList) { processList.addAll(thanos.getActivityManager().getRunningAppProcessForPackage(pkg)); } return processList; } def isPkgVisible(pkg) { return thanos.getActivityManager().isAppForeground(pkg) || thanos.getWindowManager().hasVisibleWindows(pkg); } def getProcessFrozenStatus(process) { return su.exe(\"cat /sys/fs/cgroup/uid_\" + process.getUid() + \"/pid_\" + process.getPid() + \"/cgroup.freeze\").out[0]; } def setProcessFrozenStatus(process, status) { su.exe(\"echo \" + status + \" > /sys/fs/cgroup/uid_\" + process.getUid() + \"/pid_\" + process.getPid() + \"/cgroup.freeze\"); } def main() { debug(\"收到 FCM 推送: \" + pkgName); pkgList = getPkgListByPkgName(pkgName); processList = getProcessListByPkgList(pkgList); if (processList.size() == 0) { debug(\"应用尚未运行,尝试启动应用\"); isLaunched = activity.launchProcessForPackage(pkgName); if (!isLaunched) { debug(\"启动应用失败\"); return; } else { debug(\"启动应用成功\"); } debug(\"等待应用启动完成\"); Thread.sleep(3000); processList = getProcessListByPkgList(pkgList); debug(\"需要冻结的进程列表: \" + (processName in processList)); } else { debug(\"正在运行的进程列表: \" + (processName in processList)); frozenProcessList = []; foreach(process : processList) { if (getProcessFrozenStatus(process) == \"1\") { frozenProcessList.add(process); } } if (frozenProcessList.size() == 0) { debug(\"未找到已冻结的进程\"); return; } else { debug(\"已冻结的进程列表: \" + (processName in frozenProcessList)); } debug(\"开始解冻进程\"); foreach(process : frozenProcessList) { setProcessFrozenStatus(process, \"0\"); } debug(\"解冻进程完成\"); processList = frozenProcessList; } Thread.sleep(5000); foreach(pkg : pkgList) { if (isPkgVisible(pkg)) { debug(\"应用正在前台运行,跳过冻结\"); return; } } debug(\"开始冻结进程\"); foreach(process : processList) { setProcessFrozenStatus(process, \"1\"); } debug(\"冻结进程完成\"); } main();"
]
}
]
代码:
def debug(msg) {
log.log("🚀 " + msg);
}
def getUserIdList() {
userList = context.getSystemService(context.USER_SERVICE).getUsers();
userIdList = (identifier in (userHandle in userList));
return userIdList;
}
def getPkgByNameAndUserId(pkgName, userId) {
pkg = Pkg.newPkg(pkgName, userId);
return pkg;
}
def isValidPkg(pkg) {
return thanos.getPkgManager().getAppInfo(pkg) != null;
}
def getPkgListByPkgName(pkgName) {
userIdList = getUserIdList();
res = [];
foreach(userId: userIdList) {
pkg = getPkgByNameAndUserId(pkgName, userId);
if (isValidPkg(pkg)) {
res.add(pkg);
}
}
return res;
}
def getProcessListByPkgList(pkgList) {
processList = [];
foreach(pkg : pkgList) {
processList.addAll(thanos.getActivityManager().getRunningAppProcessForPackage(pkg));
}
return processList;
}
def isPkgVisible(pkg) {
return thanos.getActivityManager().isAppForeground(pkg) || thanos.getWindowManager().hasVisibleWindows(pkg);
}
def getProcessFrozenStatus(process) {
return su.exe("cat /sys/fs/cgroup/uid_" + process.getUid() + "/pid_" + process.getPid() + "/cgroup.freeze").out[0];
}
def setProcessFrozenStatus(process, status) {
su.exe("echo " + status + " > /sys/fs/cgroup/uid_" + process.getUid() + "/pid_" + process.getPid() + "/cgroup.freeze");
}
def main() {
debug("收到 FCM 推送: " + pkgName);
pkgList = getPkgListByPkgName(pkgName);
processList = getProcessListByPkgList(pkgList);
if (processList.size() == 0) {
debug("应用尚未运行,尝试启动应用");
isLaunched = activity.launchProcessForPackage(pkgName);
if (!isLaunched) {
debug("启动应用失败");
return;
} else {
debug("启动应用成功");
}
debug("等待应用启动完成");
Thread.sleep(3000);
processList = getProcessListByPkgList(pkgList);
debug("需要冻结的进程列表: " + (processName in processList));
} else {
debug("正在运行的进程列表: " + (processName in processList));
frozenProcessList = [];
foreach(process : processList) {
if (getProcessFrozenStatus(process) == "1") {
frozenProcessList.add(process);
}
}
if (frozenProcessList.size() == 0) {
debug("未找到已冻结的进程");
return;
} else {
debug("已冻结的进程列表: " + (processName in frozenProcessList));
}
debug("开始解冻进程");
foreach(process : frozenProcessList) {
setProcessFrozenStatus(process, "0");
}
debug("解冻进程完成");
processList = frozenProcessList;
}
Thread.sleep(5000);
foreach(pkg : pkgList) {
if (isPkgVisible(pkg)) {
debug("应用正在前台运行,跳过冻结");
return;
}
}
debug("开始冻结进程");
foreach(process : processList) {
setProcessFrozenStatus(process, "1");
}
debug("冻结进程完成");
}
main();
#THANOX# #墓碑模式# #FCM推送#