Android自动dump hprof文件的功能实现
16lz
2021-01-26
要实现这个功能,必须提升权限,必须满足以下两个条件之一
1、在root的设备上运行
2、如果机子没root,需要在app的manifest文件中添加sharedUid,但是使用了这个的话,需要对apk文件进行系统签名
android:sharedUserId="android.uid.shell"
【步骤1】先准备一个工具类,用于获取进程的内存,dump hrpof文件等操作,代码如下:
** * 系统级的操作的工具类 * */public class SystemOper {private static String TAG = "SystemOper";/** * 获取应用所占用的内存大小 * * @param pkgName 应用的包名 * @return 占用内存的大小(kB),包括native heap 和 dalvik heap等,为总内存大小 */public static int getProcessMemory(String pkgName) {int memoryUsed = 0;String getMemory = "dumpsys meminfo | grep " + pkgName;ShellUtils.CommandResult getMemoryResult = ShellUtils.execCommand(getMemory, false);if (getMemoryResult.successMsg.trim().length() > 0) {String str = getMemoryResult.successMsg;int end = str.indexOf(" kB:");memoryUsed = Integer.parseInt(str.substring(0, end).trim());Log.i(TAG, "getProcessMemory: " + memoryUsed);}return memoryUsed;}/** * dump应用的hprof文件,为了保证数据的完整性,此步骤将耗时1分钟 * hprof文件存放在/sdcard/autotest/hprof路径下 * @param pkgName 进程名称 */public static void getHprof(final String pkgName) {Thread dumpThread = new Thread(new Runnable() {@Overridepublic void run() {// 1、得到进程号String findPID = getPidByName(pkgName);if (findPID == null) {return;}File srcFile = new File("/data/local/tmp/" + pkgName + ".hprof");Date date = new Date();SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd_HH:mm:ss");String time = format.format(date);File hprofFile_sdcard = new File("/sdcard/autotest/hprof/"+ pkgName + "_" + time + ".hprof");if (!hprofFile_sdcard.getParentFile().exists())hprofFile_sdcard.getParentFile().mkdirs();if (!hprofFile_sdcard.exists()) {try {hprofFile_sdcard.createNewFile();} catch (IOException e) {e.printStackTrace();}}// 2、根据进程号dumpheapString dumpHeap = "am dumpheap " + findPID + " "+ srcFile.getAbsolutePath();ShellUtils.CommandResult dumpHeapResult = ShellUtils.execCommand(dumpHeap, false);// 3、等待dump文件的生成FileOperator.waitForCompleted(srcFile);// 4、将文件拷贝到sdcard下String cpHprof = "cp " + srcFile.getAbsolutePath() + " "+ hprofFile_sdcard.getAbsolutePath();ShellUtils.CommandResult cpHprofResult = ShellUtils.execCommand(cpHprof, false);TestReport.i(TAG, "DUMP完毕!" + cpHprofResult.errorMsg + "---"+ cpHprofResult.successMsg);// 5、删除源文件srcFile.delete();}});dumpThread.start();}/** * 通过包名查找pid,如果是system权限,该方法将失效,如果进程不在,则返回null * * @param pkgName 包名 * @return pid */public static String getPidByName(String pkgName) {String findPID = "ps | grep " + pkgName;ShellUtils.CommandResult result = ShellUtils.execCommand(findPID, false);if (result.successMsg.trim().length() > 0) {String[] strs = result.successMsg.split(" ");ArrayList list = new ArrayList();for (int i = 0; i < strs.length; i++) {if (strs[i].trim().length() > 0) {list.add(strs[i]);}}return list.get(1);} else {TestReport.i(TAG, pkgName + "进程不存在!");return null;}}}
然后dump hprof文件的命令需要解释下,格式为
am dumpheap pid /data/local/tmp/pkgName.hprof
这个文件最好还是先放到tmp目录下,不同的机子权限不一样,虽然理论上这个命令是可以将hprof文件直接放到/sdcard下的,但是发现有些机子是不行的,所以为了安全起见还是放到tmp下,再拷贝出去,拷之前要确保hprof文件已经生成完毕,
FileOperator.waitForCompleted(srcFile);
这个方法参照上一篇文章
【步骤2】自己开启一个线程,不断判断SystemOper.getProcessMemory(youpkg)的值,如果大于你设的阈值,就调用SystemOper.getHprof(youpkg)
更多相关文章
- Android启动App时白屏的解决方法
- 如何在 Android(安卓)Studio 中引用不在项目文件夹中的 jar
- basic4android 开发教程翻译(二)可视化设计与猜数字程序
- Android(安卓)Studio生成签名文件,自动签名,以及获取SHA1和MD5值
- . Android內核Porting相關背景知識
- Android系统使用MediaFile类判断音频文件类型
- 使用adb和FTP从电脑给Android设备拷贝文件
- Android官方开发文档Training系列课程中文版:数据存储之键值对序
- android 安全讲座第一层 Android(安卓)APK 签名比对,防止软件被破