Android平台如何获取CPU占用率和电池电量信息

news2024/11/18 1:25:06

技术背景

我们在做Android平台GB28181设备接入模块、轻量级RTSP服务模块和RTMP推流模块的时候,遇到这样的技术诉求,开发者希望把实时CPU占用、电池信息等叠加在视频界面。

获取CPU占用率

Android平台获取CPU占用情况,可以读取/proc/stat文件,解析出各个 CPU 时间参数,然后计算出 CPU 的使用率,示例代码如下:

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Process;
import android.util.Log;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class MainActivity extends Activity {

    private Handler handler = new Handler(Looper.getMainLooper());
    private Runnable runnable;
    private long prevTotalCpuTime = 0;
    private long prevIdleCpuTime = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    // 读取 /proc/stat 文件获取 CPU 时间信息
                    BufferedReader reader = new BufferedReader(new FileReader("/proc/stat"));
                    String line = reader.readLine();
                    reader.close();

                    String[] tokens = line.split("\\s+");
                    long user = Long.parseLong(tokens[2]);
                    long nice = Long.parseLong(tokens[3]);
                    long system = Long.parseLong(tokens[4]);
                    long idle = Long.parseLong(tokens[5]);
                    long iowait = Long.parseLong(tokens[6]);
                    long irq = Long.parseLong(tokens[7]);
                    long softirq = Long.parseLong(tokens[8]);

                    long totalCpuTime = user + nice + system + idle + iowait + irq + softirq;
                    long idleCpuTime = idle;

                    // 计算 CPU 使用率
                    if (prevTotalCpuTime!= 0 && prevIdleCpuTime!= 0) {
                        long diffTotalCpuTime = totalCpuTime - prevTotalCpuTime;
                        long diffIdleCpuTime = idleCpuTime - prevIdleCpuTime;
                        float cpuUsage = ((diffTotalCpuTime - diffIdleCpuTime) / (float) diffTotalCpuTime) * 100;
                        Log.d("CPU_USAGE", "CPU Usage: " + cpuUsage + "%");
                    }

                    prevTotalCpuTime = totalCpuTime;
                    prevIdleCpuTime = idleCpuTime;

                } catch (IOException e) {
                    e.printStackTrace();
                }

                // 延迟一段时间后再次执行
                handler.postDelayed(this, 1000);
            }
        };

        // 启动获取 CPU 使用率的任务
        handler.post(runnable);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 停止任务
        handler.removeCallbacks(runnable);
    }
}

使用BatteryManager类获取电池电量

在 Android 中,可以使用BatteryManager类来获取电池电量信息。以下是具体步骤:

一、注册广播接收器

在你的 Android 组件(如 Activity 或 Service)中注册一个广播接收器来监听电池状态变化的广播。可以在onCreate方法中进行注册。

IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(batteryReceiver, filter);

这里创建了一个IntentFilter来指定要监听的广播为电池状态变化广播(Intent.ACTION_BATTERY_CHANGED),然后使用registerReceiver方法注册广播接收器。

二、创建广播接收器

创建一个广播接收器类来处理电池状态变化的广播,如下所示:

private BroadcastReceiver batteryReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
        int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
        int batteryPercentage = (level / (float)scale) * 100;
        // 这里可以根据获取到的电池电量信息进行相应的处理
    }
};

在广播接收器的onReceive方法中,可以从广播意图中获取电池电量的级别(BatteryManager.EXTRA_LEVEL)和总刻度(BatteryManager.EXTRA_SCALE),然后计算出电池电量的百分比。

三、取消注册广播接收器

在适当的时候,如组件的onDestroy方法中,取消注册广播接收器,以避免资源泄漏:

unregisterReceiver(batteryReceiver);

这样,当电池状态发生变化时,你的广播接收器将会收到通知,并可以获取到电池电量信息进行相应的处理。

需要注意的是,获取电池电量信息可能需要相应的权限。在 AndroidManifest.xml 文件中添加以下权限声明:

<uses-permission android:name="android.permission.BATTERY_STATS" />

场景应用

以大牛直播SDK的GB28181设备接入模块为例,摄像头实时视频采集,可以叠加上实时CPU占用和实时电量信息,亦或实时时间信息,会对场景带来很大益处,比如CPU占用率或电量信息,简单来说可以通过bitmap把文字读取下来,投递到底层比如jni层即可,非常方便。下面就文字和图片水印做个简短的技术普及。

文字水印

文字水印不再赘述,主要注意的是文字的大小、颜色、位置。

private int postText1Layer(int index, int left, int top) {
    Bitmap text_bitmap = makeTextBitmap("文本水印一", getFontSize()+8,
            Color.argb(255, 200, 250, 0),
            false, 0,false);

    if (null == text_bitmap)
        return 0;

    ByteBuffer buffer = ByteBuffer.allocateDirect(text_bitmap.getByteCount());
    text_bitmap.copyPixelsToBuffer(buffer);

    libPublisher.PostLayerImageRGBA8888ByteBuffer(handle_, index, left, top, buffer, 0,
            text_bitmap.getRowBytes(), text_bitmap.getWidth(), text_bitmap.getHeight(),
            0, 0, 0, 0, 0,0);

    int ret = text_bitmap.getHeight();

    text_bitmap.recycle();

    return ret;
}

png水印

png水印,除了常规的位置需要注意之外,还涉及到logo水印的大小问题,为此,我们添加了缩放效果,可以缩放后,再贴到图层,确保以更合适的比例展示在图层期望位置。

private int postPictureLayer(int index, int left, int top) {
    Bitmap bitmap = getAssetsBitmap();
    if (null == bitmap) {
        Log.e(TAG, "postPitcureLayer getAssetsBitmap is null");
        return 0;
    }

    if (bitmap.getConfig() != Bitmap.Config.ARGB_8888) {
        Log.e(TAG, "postPitcureLayer config is not ARGB_8888, config:" + Bitmap.Config.ARGB_8888);
        return 0;
    }

    ByteBuffer buffer = ByteBuffer.allocateDirect(bitmap.getByteCount());
    bitmap.copyPixelsToBuffer(buffer);

    final int w = bitmap.getWidth();
    final int h = bitmap.getHeight();
    if ( w < 2 || h < 2 )
        return 0;

    int scale_w = 0, scale_h = 0, scale_filter_mode = 0;

    final float r_w = width_ - left; // 有可能负数
    final float r_h = height_ - top; // 有可能负数

    if (w > r_w || h > r_h) {
        float s_w = w;
        float s_h = h;

        // 0.85的10次方是0.19687, 缩放到0.2倍差不多了
        for ( int i = 0; i < 10; ++i)  {
            s_w *= 0.85f;
            s_h *= 0.85f;

            if (s_w < r_w && s_h < r_h )
                break;
        }

        if (s_w > r_w || s_h > r_h)
            return 0;

        // 如果小于16就算了,太小看也看不见
        if (s_w < 16.0f || s_h < 16.0f)
            return  0;

        scale_w = align((int)(s_w + 0.5f), 2);
        scale_h = align( (int)(s_h + 0.5f), 2);
        scale_filter_mode = 3;
    }

    /*
    if ( scale_w > 0 && scale_h > 0)
        Log.i(TAG, "postTextLayer scale_w:" + scale_w + ", scale_h:" + scale_h + " w:" + w + ", h:" + h) ; */

    libPublisher.PostLayerImageRGBA8888ByteBuffer(handle_, index, left, top, buffer, 0, bitmap.getRowBytes(), w, h,
            0, 0, scale_w, scale_h, scale_filter_mode,0);

    int ret = scale_h > 0 ? scale_h : bitmap.getHeight();

    bitmap.recycle();

    return ret;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2176272.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第十三届蓝桥杯真题Java c组D.求和(持续更新)

博客主页&#xff1a;音符犹如代码系列专栏&#xff1a;蓝桥杯关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 【问题描述】 给定 n 个整数 a1, a2, , an &#xff0c;求它们两两相乘再相…

生信初学者教程(十六):GO富集分析

文章目录 介绍加载R包导入数据所需函数运行输出结果总结介绍 GO(Gene Ontology)是一个在生物信息学中广泛使用的概念,用于描述基因和基因产物的功能、它们所处的细胞位置以及它们参与的生物过程。GO项目是一个协作性的国际努力,旨在建立和维护一个适用于各种物种的、结构化…

用Python实现运筹学——Day 6: 单纯形法求解过程

一、学习内容 1. 单纯形法的详细步骤 单纯形法是通过迭代过程来优化线性规划问题的解决方案。该算法从可行解空间的一个顶点出发&#xff0c;逐步沿着可行解空间的边界移动到另一个顶点&#xff0c;直到找到最优解。单纯形法的求解过程分为以下几个步骤&#xff1a; 初始化&a…

EE trade:黄金T+D是什么意思

黄金TD&#xff0c;全称“黄金延期交割”&#xff0c;是由上海黄金交易所推出的标准化合约&#xff0c;允许投资者以保证金的形式进行黄金交易&#xff0c;并可以选择当日交割或延期交割。它为国内投资者提供了一个全新的黄金投资渠道&#xff0c;但也存在一些风险&#xff0c;…

Linux进程切换以及调度算法

目录 Linux进程切换以及调度算法 Linux进程切换介绍 前置知识 进程切换过程分析 调度算法 补充知识 Linux进程切换以及调度算法 Linux进程切换介绍 前面提到&#xff0c;分时操作系统下&#xff0c;CPU会在多个进程中做高速切换以实现多个进程看似同时执行的&#xff0…

会员办理--足浴店系统开发代码———未来之窗行业应用跨平台架构

function fun_会员查询_事务_新增(){var 未来之窗vos对话框_内容 ;var title"test";var 未来之窗vos对话框_id"hjksgfjkkhkj";CyberWin_Dialog.layer(未来之窗vos对话框_内容,{type:"frame",title:"新增会员",move:false,width:"…

828华为云征文|WordPress部署

目录 前言 一、环境准备 二、远程连接 三、WordPress简介 四、WordPress安装 1. 基础环境安装 ​编辑 2. WordPress下载与解压 3. 创建站点 4. 数据库配置 总结 前言 WordPress 是一个非常流行的开源内容管理系统&#xff08;Content Management System, CMS&#xf…

FTP 服务器 linux安装

文章目录 前言一、了解二、安装启动匿名连接 三、创建用户1. 创建系统用户2. 连接3. 连接不上&#xff1f; 5004. 还是连接不上&#xff1f; 5005. 还还还是连不上&#xff1f;530 补充关于创建用户useradd 命令如何设置用户不能登录shell不用系统指定的家目录 vsftpd 配置chro…

Python | Leetcode Python题解之第443题压缩字符串

题目&#xff1a; 题解&#xff1a; class Solution:def compress(self, chars: List[str]) -> int:def reverse(left: int, right: int) -> None:while left < right:chars[left], chars[right] chars[right], chars[left]left 1right - 1n len(chars)write lef…

Android15音频进阶之新播放器HwAudioSource(八十六)

简介: CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布:《Android系统多媒体进阶实战》🚀 优质专栏: Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏: 多媒体系统工程师系列【原创干货持续更新中……】🚀 优质视频课程:AAOS车载系统+…

面试扩展知识点

1.C语言中分为下面几个存储区 栈(stack): 由编译器自动分配释放堆(heap): 一般由程序员分配释放&#xff0c;若程序员不释放&#xff0c;程序结束时可能由OS回收全局区(静态区): 全局变量和静态变量的存储是放在一块的&#xff0c;初始化的全局变量和静态变量在一块区域&#…

线性表二——栈stack

第一题 #include<bits/stdc.h> using namespace std; stack<char> s; int n; string ced;//如何匹配 出现的右括号转换成同类型的左括号&#xff0c;方便我们直接和栈顶元素 char cheak(char c){if(c)) return (;if(c]) return [;if(c}) return {;return \0;/…

MySQL 高级 - 第十五章 | MySQL 事务日志

目录 第十五章 MySQL 事务日志15.1 redo 日志15.1.1 为什么需要 redo 日志15.1.2 redo 日志的优点与特点15.1.3 redo 的组成15.1.4 redo 的整体流程15.1.5 redo log 的刷盘策略15.1.6 不同刷盘策略演示15.1.7 写入 redo log buffer 过程15.1.8 redo log file 15.2 undo 日志15.…

lombok详细教程(详解)

Lombok 极速上手 此笔记来自于b站白马 背景 ⚠️ 开始学习Lombok前至少需要保证完成 JavaSE 课程中的注解部分&#xff0c;本课程采用的版本为 Java17 我们发现&#xff0c;在以往编写项目时&#xff0c;尤其是在类进行类内部成员字段封装时&#xff0c;需要编写大量的 get…

看480p、720p、1080p、2k、4k、视频一般需要多大带宽呢?

看视频都喜欢看高清&#xff0c;那么一般来说看电影不卡顿需要多大带宽呢&#xff1f; 以4K为例&#xff0c;这里引用一位网友的回答&#xff1a;“视频分辨率4092*2160&#xff0c;每个像素用红蓝绿三个256色(8bit)的数据表示&#xff0c;视频帧数为60fps&#xff0c;那么一秒…

基于微信小程序爱心领养小程序设计与实现(源码+参考文档+定制开发)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

excel统计分析(5): 非线性回归分析

非线性回归模型分类 非线性回归分析和预测模型包括&#xff1a;指数、对数、幂函数、多项式等。 &#xff08;1&#xff09;指数回归模型 指数回归模型适用于因变量随自变量的增加而迅速增长或减少的情况。 Yβ0⋅e^(β1⋅X) 其中&#xff0c;e是自然对数的底数&#xff0c;…

锐捷 NBR 1300G路由器 越权CLI命令执行漏洞

漏洞描述 锐捷NBR 1300G路由器 越权CLI命令执行漏洞&#xff0c;guest账户可以越权获取管理员账号密码 漏洞复现 FOFA title"锐捷网络 --NBR路由器--登录界面" 请求包 POST /WEB_VMS/LEVEL15/ HTTP/1.1 Host: Connection: keep-alive Content-Length: 73 Autho…

[SAP ABAP] SELECTION-SCREEN

SELECTION-SCREEN用来调节系统生成的画面 REPORT z437_test_2024.TABLES: mara, zdbt_sch_437.SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001. " Title1 PARAMETERS:p_1 DEFAULT A,p_2 TYPE char10. SELECTION-SCREEN END OF BLOCK b1.SELECTION-SCREEN …

深入理解同步和异步与reactor和proactor模式

在现代网络编程中&#xff0c;I/O 设计模式对于提高性能和资源利用率至关重要。本文将探讨两种主要的网络 I/O 设计模式&#xff1a;同步 I/O 和异步 I/O&#xff0c;以及它们的实现方式。 同步 I/O 同步 I/O 模式要求用户通过系统调用函数&#xff0c;如 read(), write(), c…