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

​技术背景

我们在做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 文件中添加以下权限声明:

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
            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
}

阅读全文
下载说明:
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.dandroid.cn/archives/22329,转载请注明出处。
0

评论0

显示验证码
没有账号?注册  忘记密码?