feat(mmp): Hook 无心跳时自动唤醒或强停重开 TNG

领取台检测开启时,进程在跑但心跳过期会先进历史页唤醒,仍无效则 force-stop 重建 Hook。
This commit is contained in:
mars
2026-08-05 17:29:36 +08:00
parent abf41b9ab6
commit ae65351d8e
2 changed files with 114 additions and 7 deletions

View File

@@ -60,6 +60,9 @@ public class MmpClaimActivity extends MiracleGardenActivity<ActivityMmpClaimBind
private boolean autoWatchWhileOpen = true;
private boolean autoLaunchTngIfKilled = true;
private long lastTngLaunchAt;
/** 0=未处理 1=已唤醒/进历史 2=已强停重开 */
private int hookRecoverStep;
private long lastHookRecoverAt;
private final Runnable watchRunnable = this::watchTngOnce;
/** null=检测中 true=通 false=不通 */
private Boolean debugServerOk;
@@ -342,13 +345,17 @@ public class MmpClaimActivity extends MiracleGardenActivity<ActivityMmpClaimBind
return;
}
boolean alive = TngProcessHelper.isRunning(this);
if (autoWatchWhileOpen && !alive && autoLaunchTngIfKilled) {
long now = System.currentTimeMillis();
if (now - lastTngLaunchAt > 60_000L) {
if (TngProcessHelper.launch(this)) {
lastTngLaunchAt = now;
Toast.makeText(this, "检测到 TNG 已退出,正在重新打开…", Toast.LENGTH_SHORT).show();
if (autoWatchWhileOpen && autoLaunchTngIfKilled) {
if (!alive) {
long now = System.currentTimeMillis();
if (now - lastTngLaunchAt > 60_000L) {
if (TngProcessHelper.launch(this)) {
lastTngLaunchAt = now;
Toast.makeText(this, "检测到 TNG 已退出,正在重新打开…", Toast.LENGTH_SHORT).show();
}
}
} else {
maybeRecoverStaleHook();
}
}
updateConnStatus();
@@ -359,6 +366,63 @@ public class MmpClaimActivity extends MiracleGardenActivity<ActivityMmpClaimBind
handler.postDelayed(watchRunnable, 12_000L);
}
/**
* TNG 还在跑但 Hook 长时间无心跳:先唤醒/进历史页,仍无效再强停重开。
*/
private void maybeRecoverStaleHook() {
long hookAt = MmpHookStatus.lastAliveAt(this);
long age = hookAt > 0 ? System.currentTimeMillis() - hookAt : Long.MAX_VALUE;
if (age <= 3 * 60_000L) {
hookRecoverStep = 0;
return;
}
long now = System.currentTimeMillis();
boolean bounce = MmpLocalSettings.load(this)
.optBoolean("autoBounceHistoryOnDisconnect", true);
if (hookRecoverStep == 0) {
if (now - lastHookRecoverAt < 45_000L) {
return;
}
lastHookRecoverAt = now;
hookRecoverStep = 1;
boolean ok = bounce
? TngProcessHelper.openMoneyPacketHistory(this)
: TngProcessHelper.launch(this);
if (ok) {
Toast.makeText(this, "Hook 无心跳,正在唤醒 TNG…", Toast.LENGTH_SHORT).show();
}
return;
}
if (hookRecoverStep == 1) {
if (now - lastHookRecoverAt < 90_000L) {
return;
}
// 唤醒后仍无心跳 → 强停重建
lastHookRecoverAt = now;
hookRecoverStep = 2;
Toast.makeText(this, "仍无心跳,强制重启 TNG…", Toast.LENGTH_SHORT).show();
new Thread(() -> {
boolean ok = TngProcessHelper.forceStopAndLaunch(this);
runOnUiThread(() -> {
if (ok) {
lastTngLaunchAt = System.currentTimeMillis();
} else {
Toast.makeText(this, "强制重启 TNG 失败", Toast.LENGTH_SHORT).show();
hookRecoverStep = 0;
}
});
}, "mmp-hook-recover").start();
return;
}
// step 2 后隔 3 分钟仍无心跳,再重试一轮
if (now - lastHookRecoverAt > 3 * 60_000L) {
hookRecoverStep = 0;
}
}
private void pingDebugServer() {
lastDebugPingAt = System.currentTimeMillis();
MmpSettingsClient.pingHealth(ok -> runOnUiThread(() -> {
@@ -405,7 +469,9 @@ public class MmpClaimActivity extends MiracleGardenActivity<ActivityMmpClaimBind
}
String watchPart = autoWatchWhileOpen
? (autoLaunchTngIfKilled ? "检测:开(杀掉会拉起)" : "检测:开(不自动拉起)")
? (autoLaunchTngIfKilled
? "检测:开(退出/无心跳会拉起)"
: "检测:开(不自动拉起)")
: "检测:关";
String debugPart;

View File

@@ -111,4 +111,45 @@ public final class TngProcessHelper {
return false;
}
}
/** 打开红包历史页,触发 Hook onResume / 自动拉取 */
public static boolean openMoneyPacketHistory(Context context) {
if (context == null) {
return false;
}
try {
Intent intent = new Intent();
intent.setClassName(TNG_PACKAGE,
"my.com.tngdigital.funding.moneypacket.create.ui.MoneyPacketHistoryActivity");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_NO_ANIMATION);
context.startActivity(intent);
Log.i(TAG, "opened MoneyPacketHistoryActivity");
return true;
} catch (Exception e) {
Log.w(TAG, "open history fail, fallback launch: " + e.getMessage());
return launch(context);
}
}
/** 强制停止 TNG优先 su */
public static boolean forceStop(Context context) {
String out = shell("su -c am force-stop " + TNG_PACKAGE);
if (TextUtils.isEmpty(out)) {
out = shell("am force-stop " + TNG_PACKAGE);
}
Log.i(TAG, "force-stop TNG done");
return true;
}
/** 强停后再打开,用于 Hook 假死重建 */
public static boolean forceStopAndLaunch(Context context) {
forceStop(context);
try {
Thread.sleep(900L);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return launch(context);
}
}