Android-Framework pm list packages和pm install返回指定应用信息
一、环境
高通 Android 13
注:Android10 和Android13有些差异,代码位置不变,参照修改即可
二、pm简单介绍
pm工具为包管理(package manager)的简称
可以使用pm工具来执行应用的安装和查询应用宝的信息、系统权限、控制应用
pm工具是Android开发与测试过程中必不可少的工具,shell命令格式如下:
pm <command>
kona:/ # which pm
/system/bin/pm
kona:/ #
kona:/ # file system/bin/pm
system/bin/pm: /system/bin/sh script
三、pm命令对应的源码位置如下
frameworks/base/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
这里通过修改源码,达到以下两个效果:
1、pm list packages -3 返回详细应用信息;2、pm install 返回包名和启动Activity
源码修改:
@@ -145,6 +145,11 @@ import java.util.concurrent.CountDownLatch;import java.util.concurrent.LinkedBlockingQueue;import java.util.concurrent.TimeUnit;+import android.app.usage.StorageStats;
+import android.app.usage.StorageStatsManager;
+import java.util.UUID;
+import java.util.HashSet;
+class PackageManagerShellCommand extends ShellCommand {/** Path for streaming APK content */private static final String STDIN_PATH = "-";
@@ -623,6 +628,7 @@ class PackageManagerShellCommand extends ShellCommand {null /* splitApkPaths */, null /* splitRevisionCodes */,apkLite.getTargetSdkVersion(), null /* requiredSplitTypes */,null /* splitTypes */);
+ params.sessionParams.setAppPackageName(pkgLite.getPackageName());sessionSize += InstallLocationUtils.calculateInstalledSize(pkgLite,params.sessionParams.abiOverride, fd.getFileDescriptor());} catch (IOException e) {
@@ -842,7 +848,7 @@ class PackageManagerShellCommand extends ShellCommand {}private int runListPackages(boolean showSourceDir, boolean showSdks) throws RemoteException {
- final String prefix = showSdks ? "sdk:" : "package:";
+ final String prefix = showSdks ? "sdk:" : "PackageName:";final PrintWriter pw = getOutPrintWriter();int getFlags = 0;boolean listDisabled = false, listEnabled = false;
@@ -985,7 +991,7 @@ class PackageManagerShellCommand extends ShellCommand {stringBuilder.append(info.applicationInfo.sourceDir);stringBuilder.append("=");}
- stringBuilder.append(name);
+ stringBuilder.append(name+ ";");if (showVersionCode) {stringBuilder.append(" versionCode:");if (info.applicationInfo != null) {
@@ -998,6 +1004,47 @@ class PackageManagerShellCommand extends ShellCommand {stringBuilder.append(" installer=");stringBuilder.append(mInterface.getInstallerPackageName(info.packageName));}
+
+
+
+ if (listThirdParty) {
+ stringBuilder.append(" Activity:");
+ stringBuilder.append(getClassName(info.packageName) + ";");
+
+ stringBuilder.append(" Label:");
+ stringBuilder.append(mContext.getPackageManager().getApplicationLabel(info.applicationInfo) + ";");
+
+ //app size
+ String sourceDir = info.applicationInfo.sourceDir;
+ StorageStatsManager storageStatsManager = (StorageStatsManager) mContext.getSystemService(Context.STORAGE_STATS_SERVICE);
+ StorageManager storageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
+ StorageStats storageStats =null;
+ try{
+ UUID uuid = storageManager.getUuidForPath(new File(sourceDir));
+ storageStats = storageStatsManager.queryStatsForPackage(uuid, info.packageName,UserHandle.getUserHandleForUid(info.applicationInfo.uid));
+ }catch(IOException e){
+ e.printStackTrace();
+ }catch(NameNotFoundException e){
+ e.printStackTrace();
+ }
+ if(storageStats != null) {
+ long appSize = storageStats.getAppBytes() + storageStats.getCacheBytes() + storageStats.getDataBytes();
+
+ stringBuilder.append(" Size:");
+ stringBuilder.append(appSize + ";");
+ }
+
+ //version name
+ stringBuilder.append(" VersionName:");
+ stringBuilder.append(info.versionName + ";");
+
+ //Uid
+ stringBuilder.append(" Uid:");
+ stringBuilder.append( info.applicationInfo.uid + ";");
+
+ }
+
+List<String> uids = out.computeIfAbsent(stringBuilder.toString(), k -> new ArrayList<>());
@@ -1006,6 +1053,7 @@ class PackageManagerShellCommand extends ShellCommand {}}}
+for (Map.Entry<String, List<String>> entry : out.entrySet()) {pw.print(entry.getKey());List<String> uids = entry.getValue();
@@ -1018,6 +1066,58 @@ class PackageManagerShellCommand extends ShellCommand {return 0;}+
+ private String getClassName(String packageName){
+ try {
+ Intent intent = new Intent();
+ Intent baseIntent = intent;
+
+ baseIntent = new Intent(Intent.ACTION_MAIN);
+ baseIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+ baseIntent.setPackage(packageName);
+
+ if (baseIntent != null) {
+ Bundle extras = intent.getExtras();
+ intent.replaceExtras((Bundle) null);
+ Bundle uriExtras = baseIntent.getExtras();
+ baseIntent.replaceExtras((Bundle) null);
+ if (intent.getAction() != null && baseIntent.getCategories() != null) {
+ HashSet<String> cats = new HashSet<String>(baseIntent.getCategories());
+ for (String c : cats) {
+ baseIntent.removeCategory(c);
+ }
+ }
+ intent.fillIn(baseIntent, Intent.FILL_IN_COMPONENT | Intent.FILL_IN_SELECTOR);
+ if (extras == null) {
+ extras = uriExtras;
+ } else if (uriExtras != null) {
+ uriExtras.putAll(extras);
+ extras = uriExtras;
+ }
+ intent.replaceExtras(extras);
+ }
+
+ mTargetUser = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+ Binder.getCallingUid(), mTargetUser, false, false, null, null);
+
+ ResolveInfo ri = mInterface.resolveIntent(intent, intent.getType(), mQueryFlags,
+ mTargetUser);
+ if(ri != null && ri.activityInfo.name != null){
+ return ri.activityInfo.name;
+ }else{
+ return "NULL";
+ }
+ } catch (RemoteException e) {
+ throw new RuntimeException("Failed calling service", e);
+ } catch (Exception e){
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ }
+
+
+
+
+private int runListPermissionGroups() throws RemoteException {final PrintWriter pw = getOutPrintWriter();final List<PermissionGroupInfo> pgs = mPermissionManager.getAllPermissionGroups(0);
@@ -1464,6 +1564,14 @@ class PackageManagerShellCommand extends ShellCommand {}abandonSession = false;//pm install 时,返回指定格式
+ if (params.sessionParams.appPackageName != null) {
+ if (getClassName(params.sessionParams.appPackageName) != null){
+ pw.print(params.sessionParams.appPackageName);
+ pw.println("/" + getClassName(params.sessionParams.appPackageName));
+ }
+ }
+
+if (params.sessionParams.isStaged && params.stagedReadyTimeoutMs > 0) {return doWaitForStagedSessionReady(sessionId, params.stagedReadyTimeoutMs, pw);}
相关文章:
Android-Framework pm list packages和pm install返回指定应用信息
一、环境 高通 Android 13 注:Android10 和Android13有些差异,代码位置不变,参照修改即可 二、pm简单介绍 pm工具为包管理(package manager)的简称 可以使用pm工具来执行应用的安装和查询应用宝的信息、系统权限、…...
CSS
什么是CSS? CSS是一门语言,用于控制网页表现 CSS(Cascading Style Sheet):层叠样式表 W3C标准:网页主要由三部分组成 结构:HTML表现:CSS行为:JavaScript CSS导入方式…...
算法详解——选择排序和冒泡排序
一、选择排序 选择排序算法的执行过程是这样的:首先,算法遍历整个列表以确定最小的元素,接着,这个最小的元素被置换到列表的开头,确保它被放置在其应有的有序位置上。接下来,从列表的第二个元素开始&#x…...
图论(蓝桥杯 C++ 题目 代码 注解)
目录 迪杰斯特拉模板(用来求一个点出发到其它点的最短距离): 克鲁斯卡尔模板(用来求最小生成树): 题目一(蓝桥王国): 题目二(随机数据下的最短路径&#…...
矩阵起源新一年喜报连连!
新春伊始 矩阵起源向大家分享 一连串好消息 首先,公司创始人兼CEO王龙先生获评“2023深圳创新突出贡献人物“。这一荣誉是对其在推动数据库行业技术创新和产品开发方面所做出的卓越贡献的认可。他的领导力和创新精神不仅引领我司取得了显著的成就,也为…...
牛客——紫魔法师(并查集)
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网 题目描述 “サーヴァント、キャスター、Medea。”--紫魔法师 给出一棵仙人掌(每条边最多被包含于一个环,无自环,无重边,保证连通),要求用最少的…...
最新WooCommerce教程指南-如何搭建B2C外贸独立站
WooCommerce是全球最受欢迎的开源电子商务平台之一。它基于WordPress建站,只需一键安装即可使用。该平台提供了丰富的功能,包括产品发布、库存管理、支付网关和运输发货等,可以帮助搭建各种类型的电子商务网站。相比其他竞争对手,…...
一文教会你SpringBoot是如何启动的
SpringBoot启动流程分析 流程图 源码剖析 运行Application.run()方法 我们在创建好一个 SpringBoot 程序之后,肯定会包含一个类:xxxApplication,我们也是通过这个类来启动我们的程序的(梦开始的地方),而…...
车载测试面试:各大车企面试题汇总
本博主可协助大家成功进军车载测试行业 TBOX 深圳 涉及过T-BOX测试吗Ota升级涉及的台架环境是什么样的?上车实测之前有没有一个仿真环境台架环境都什么零部件T-BOX了解多少Linux和shell有接触吗 单片机uds诊断是在实车上座的吗 uds在实车上插的那口 诊断仪器是哪…...
Qt散文一
Qt的事件分为普通事件和系统事件,普通事件比如用户按下键盘,系统事件比如定时器事件。事件循环的开始是从main函数的QApplication,然后调用exec()开始的,在执行exec()函数之后,程序将进入事件循环来监听应用程序的事件…...
MySQL学习Day32——数据库备份与恢复
在任何数据库环境中,总会有不确定的意外情况发生,比如例外的停电、计算机系统中的各种软硬件故障、人为破坏、管理员误操作等是不可避免的,这些情况可能会导致数据的丢失、 服务器瘫痪等严重的后果。存在多个服务器时,会出现主从服…...
阅读基础知识
一 网络 1. 三次握手四次挥手 三次握手:为了建立长链接进行交互即建立一个会话,使用 http/https 协议 ① 客户端产生初始化序列号 Seqx ,向服务端发送建立连接的请求报文,将 SYN1 同步序列号; ② 服务端接收建立连接…...
【NestJS 编程艺术】1. NestJS设计模式深度解析:构建高效、可维护的服务端应用
在当今快速发展的软件开发领域,Node.js凭借其轻量级和高性能的特点,已经成为了构建服务端应用的首选技术之一。然而,随着应用规模的扩大,传统的Node.js框架如Express和Koa可能在架构设计和代码组织上显得力不从心。这时࿰…...
QT中connect()的参数5:Qt::DirectConnection、Qt::QueuedConnection区别
原文链接:https://blog.csdn.net/Dasis/article/details/120916993 connect用于连接QT的信号和槽,在qt编程过程中不可或缺。它其实有第5个参数,只是一般使用默认值,在满足某些特殊需求的时候可能需要手动设置。 Qt::AutoConnect…...
VXLAN学习笔记
声明:该博客内容大部分参考参考链接整理 什么是VXLAN? VXLAN(Virtual Extensible LAN)即虚拟扩展局域网,是大二层网络中广泛使用的网络虚拟化技术。在源网络设备与目的网络设备之间建立一条逻辑VXLAN隧道,采用MAC in UDP的封装方…...
全排列的不同写法(茴字的不同写法)及对应的时间开销
资源课件: CS106B-recursion-pptstanford library-timer.hstanford library-set.h 不同的方法 1------ Set<string> permutations1Rec(string remaining) {Set<string> res;if(remaining.size() 0) {res "";}else {for(int i 0; i <…...
权衡后台数据库设计中是否使用外键
目录 引言 外键简介 对比 真实后台项目中的权衡 结论 引言 在大学学习数据库课程时,我们会早早的接触到外键这一概念,同时我相信大部分人在懂了外键的概念后都会觉得外键很重要,在涉及多表一定要用,但后来在我接触到真实项目…...
ChatGPT提示词方法的原理
关于提示词,我之前的一些文章可以参考: 【AIGC】AI作图最全提示词prompt集合(收藏级)https://giszz.blog.csdn.net/article/details/134815245?ydrefereraHR0cHM6Ly9tcC5jc2RuLm5ldC9tcF9ibG9nL21hbmFnZS9hcnRpY2xlP3NwbT0xMDExL…...
计算机网络 谢希仁(001-1)
计算机网络-方老师 总时长 24:45:00 共50个视频,6个模块 此文章包含1.1到1.4的内容 简介 1.1计算机网络的作用 三网融合(三网合一) 模拟信号就是连续信号 数字信号是离散信号 1.2互联网概述 以前2兆带宽就要98 现在几百兆带宽也就几百块 …...
Windows,MacOS,Linux下载python并配置环境图文讲解
Windows 打开python官网 点击download 点击黄色按钮 另存为 打开文件 全选 配置安装路径 安装中 关闭路径长度限制 完成 验证 同时按住winr(win就是空格键左边的东西) 输入cmd 键入python,如果出现版本(红框)即安装成功 MacOS 同理打开python官网 点击最新版本 拖…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
