通过AlarmManager + Service + BroadcastReceiver创建一个定时任务,获取CPU温度

801 阅读2分钟

1,定时任务的搭建,先启动一个Service,然后在onStartCommand中,通过AlarmManager创建一个定时器

代码:

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {

        GlobalScope.launch(Dispatchers.Main) {
            //获取CPU温度
            val temperature = GetCpuInfo.getCPUTemperature(0)
            //获取一个Messenger用来发送handler的message
            val messenger = intent!!.extras.get("messenger") as Messenger
            //创建定时任务
            val alarmManager = getSystemService(ALARM_SERVICE) as AlarmManager
            //定时间隔,一个小时 1 * 60分钟 * 60秒钟 * 1000毫秒
            val alarmTime = 1 * 60 * 60 * 1000
            //发送广播的时间:为当前系统时间 + 间隔时间
            val targetTime: Long = SystemClock.elapsedRealtime() + alarmTime
            //注册定时任务的接收广播
            val i = Intent(applicationContext, AlarmReceiver::class.java)
            val bundle = Bundle()
            Log.e("TAG", " AlarmService to AlarmReceiver $temperature  ")
            bundle.putInt("temperature", temperature)
            bundle.putParcelable("messenger", messenger)
            i.putExtras(bundle)
            val pendingIntent = PendingIntent.getBroadcast(
                applicationContext,
                0,
                i,
                //这个FLAG表示:Flag indicating that if the described PendingIntent already exists, then keep it but replace its extra data with what is in this new Intent. 即会替换掉前一个PendingIntent的extra data如果不设置,那么每次传的值不会生效,永远第一次注册广播时传入的值
                PendingIntent.FLAG_UPDATE_CURRENT
            )
            //Schedule an alarm. 
            //参数:type = AlarmManager.ELAPSED_REALTIME_WAKEUP,设置为这个参数,将会唤醒设备 
            alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, targetTime, pendingIntent)
        }
        return super.onStartCommand(intent, flags, startId)
    }

2,在AlarmReceiver这个广播中,接收定时任务发送的消息,然后startService,继续执行service的onStartCommand()方法,开启下一个定时流程

代码:

class AlarmReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        //获取发送广播时的传输的Bundle
        val bundle = intent.extras
        val temperature = bundle.getInt("temperature")
        val messenger = bundle.getParcelable("messenger") as Messenger
        Log.e("TAG", " AlarmReceiver  get  temperature  $temperature  ")
        //创建一个Message,然后通过Messenger发送,通过Handler回调接收
        val msg = Message()
        msg.what = temperature
        messenger.send(msg)
        //重新startService
        val intent = Intent(context, AlarmService::class.java)
        intent.putExtra("messenger", messenger)
        context.startService(intent)
    }
}

3,在Activity的Handler中,接收定时任务发送的消息,然后执行这个时段要执行的任务 在Activity onCreate时候,第一次启动承载定时器的服务

代码

class CPUInfoActivity : AppCompatActivity() {
    var temperature = 0
    val handler: Handler = object : Handler() {
        override fun handleMessage(msg: Message?) {
            if (null != msg) {
                temperature = msg.what
                GlobalScope.launch(Dispatchers.Main) {
                    val text = cpuTemp.text
                    cpuTemp.text =
                        "$text \n" + "当前CPU温度为 ${temperature}°  时间:${getCurrentTime()}"
                }
            }
        }
    }

    private fun getCurrentTime(): String {
        val year = Calendar.getInstance().get(Calendar.YEAR)
        val month = Calendar.getInstance().get(Calendar.MONTH) + 1
        val day = Calendar.getInstance().get(Calendar.DAY_OF_MONTH)
        val hours = Calendar.getInstance().get(Calendar.HOUR_OF_DAY)
        val minute = Calendar.getInstance().get(Calendar.MINUTE)
        return "${year}${month}${day}${hours}${minute}分"
    }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_cpu_info)
        //启动Activity的时候,启动定时任务的服务
        val intent = Intent(this, AlarmService::class.java)
        intent.putExtra("messenger", Messenger(handler))
        startService(intent)
    }

4,获取CPU温度,需要有root权限,有条件的可以给apk打系统签名即可

代码

object GetCpuInfo {
    suspend fun getCPUTemperature(index: Int): Int {
        var temperature = 0
        val job = GlobalScope.launch(Dispatchers.Default) {
            try {
            //在系统目录/sys/class/thermal/thermal_zone0/temp下,cat temp文件,获取的数据就是当前CPU温度,在/sys/class/thermal/目录下,会有好多个thermal_zone*文件,*从0开始递增,所以查出来的数据为0或者没有这个文件的时候,去查下一个
                val args =
                    arrayListOf("/system/bin/cat", "/sys/class/thermal/thermal_zone$index/temp")
                val cmd = ProcessBuilder(args)
                val process = cmd.start()
                val ins = process.inputStream
                val byte = ByteArray(24)
                var result = ""
                var size = 0
                while ((ins.read(byte).also { size = it }) != -1) {
                    val resultByte = ByteArray(size)
                    for (index in resultByte.indices) {
                        resultByte[index] = byte[index]
                    }
                    result += String(resultByte)
                }
                ins.close()
                if (result.isNotEmpty()) {
                    var resultInt = result.trim().toInt()
                    if (resultInt > 1000) {
                        resultInt /= 1000
                    }
                    temperature = resultInt
                } else {
                    if (index < 10) {
                        getCPUTemperature(index + 1)
                    }
                }
            } catch (e: Exception) {
                e.printStackTrace()
                if (index < 10) getCPUTemperature(index + 1)
            }
        }
        job.join()
        return temperature
    }
}

参考文档:

AlarmManager: developer.android.google.cn/reference/a… PendingIntent: developer.android.google.cn/reference/a…