摘要
APP 目的
该APP作用:存在2个wakeLock,旨在触发功耗异常中的wakeLock频繁唤醒的检测
- 永久不释放wakeLock
- 定时申请和释放wakeLock
测试方法:
- H手机和T手机、其他手机进行安装该apk.
- 所有手机都需要设置应用为白名单。
H手机:手机管家->应用启动设置:允许自启动、允许关联启动、允许后台启动
T手机:手机管家->自启动管理:允许自启动 3. 启动该apk,并看到有消息通知栏出现,则按home键回到桌面,拔USB,灭屏5分钟 4. 灭屏5分钟后,亮屏查看是否有耗电异常被检测出来。例如下图
APP demo
1. 界面
package com.sufadi.blockwakelock
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.sufadi.commlib.services.ForegroundService
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 设置进程优先级为前台,基本保活
startService(Intent(this, ForegroundService::class.java))
/**
* 设置多个wakeLock
* 1. 永远存在一个不释放的锁
* 2. 定时锁,每隔1分钟申请一次锁
*/
startService(Intent(this, WakeLockServicer::class.java))
}
}
1.1 前台进程设置
核心函数:startForeground
package com.sufadi.commlib.services
import android.content.Intent
import android.os.IBinder
import android.app.*
import android.content.Context
import android.util.Log
import com.sufadi.commlib.R
class ForegroundService: Service() {
val TAG = "ForegroundService"
val FORGROUND_ID = 0x88
override fun onCreate() {
super.onCreate()
startMyForeground()
}
override fun onDestroy() {
super.onDestroy()
stopForeground(true)
}
override fun onBind(intent: Intent?): IBinder? {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
private fun startMyForeground() {
Log.d(TAG, "startMyForeground show notification")
Log.d(TAG, "PhoneDataService startMyForeground sdk :" + android.os.Build.VERSION.SDK_INT)
val nb = Notification.Builder(this)
if (android.os.Build.VERSION.SDK_INT >= 26) {
val CHANNEL_ONE_ID = "channel_id_foreground"
val CHANNEL_ONE_NAME = "Channel One"
var notificationChannel: NotificationChannel? = null
notificationChannel = NotificationChannel(
CHANNEL_ONE_ID,
CHANNEL_ONE_NAME, NotificationManager.IMPORTANCE_LOW
)
nb.setChannelId(CHANNEL_ONE_ID)
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
manager.createNotificationChannel(notificationChannel)
}
nb.setSmallIcon(R.mipmap.ic_launcher)
nb.setContentTitle(getString(R.string.notification_title))
nb.setContentText(getString(R.string.notification_Content))
try {
startForeground(FORGROUND_ID, nb.build())
} catch (e: Exception) {
e.printStackTrace()
}
}
}
2. WakeLock的申请
设置多个wakeLock
- 永远存在一个不释放的锁
- 定时锁,每隔1分钟申请一次锁
上述主要使用wakeLock和Alarm的SDK即可
package com.sufadi.blockwakelock
import android.annotation.SuppressLint
import android.app.AlarmManager
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.IBinder
import android.os.PowerManager
import android.os.SystemClock
import android.util.Log
import com.sufadi.commlib.utils.AlertWakeLock
/**
* 设置多个wakeLock
* 1. 永远存在一个不释放的锁
* 2. 定时锁,每隔1分钟申请一次锁
*/
class WakeLockServicer: Service() {
companion object {
val TAG_NORMAL_WAKELOCK = "tag_normal_wakelock"
val TAG_NEVER_RELEASE_WAKELOCK = "tag_never_release_wakelock"
}
private var count = 0
private var mNormalWakeLock: PowerManager.WakeLock? = null
private var mNeverReleaseWakeLock: PowerManager.WakeLock? = null
private var mAlarm: AlarmManager? = null
private var mAlarmListener: AlarmManager.OnAlarmListener? = null
override fun onBind(p0: Intent?): IBinder? {
return null
}
/*
Flag Value CPU Screen Keyboard
PARTIAL_WAKE_LOCK On Off Off 0x00000001 1
SCREEN_DIM_WAKE_LOCK On Dim Off 0x00000006 6
SCREEN_BRIGHT_WAKE_LOCK On Bright Off 0x0000000a 10
FULL_WAKE_LOCK On Bright Bright 0x0000001a 26
*/
@SuppressLint("InvalidWakeLockTag")
override fun onCreate() {
super.onCreate()
mAlarm = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val pm = getSystemService(Context.POWER_SERVICE) as PowerManager
mNormalWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG_NORMAL_WAKELOCK)
mNeverReleaseWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG_NEVER_RELEASE_WAKELOCK)
mNormalWakeLock?.acquire()
mNeverReleaseWakeLock?.acquire()
setAlarm(60000, "wakelock acquire count:" + count++)
Log.d("WakelockStats", "NeverReleaseWakeLock.acquire() & NormalWakeLock.acquire()")
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
return super.onStartCommand(intent, flags, startId)
}
override fun onDestroy() {
super.onDestroy()
mNormalWakeLock?.release()
mNeverReleaseWakeLock?.release()
Log.d("WakelockStats", "NeverReleaseWakeLock.onDestroy() & NormalWakeLock.onDestroy()")
}
private fun setAlarm(delay: Long, reason: String) {
val mNextAlarmTime = SystemClock.elapsedRealtime() + delay
if (mAlarmListener == null) {
mAlarmListener = AlarmManager.OnAlarmListener {
mNormalWakeLock?.release()
mNormalWakeLock?.acquire()
Log.d("WakelockStats", "NormalWakeLock.release() & NormalWakeLock.acquire()")
}
}
mAlarm?.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP, mNextAlarmTime, 0, reason, mAlarmListener, null)
}
}
|