2025年4月1日 星期二 乙巳(蛇)年 正月初二 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > 安卓(android)开发

提取系统apk

时间:02-08来源:作者:点击数:41

提取系统apk

公司有个Android设备,里面内置了一款厂家自带的应用,该应该里面有一些提示语音,我想要把厂家的应用提取出来,以便获取应用内的语音资源,于是安装了一个APK Extractor,但是这个应用里没有列出来我需要的应用,系统应用也显示了,就是没有显示我需要的那个应用。经过百度,找到了另一种提取方式,成功的提取到了我需要的apk。

  1. 通过adb命令列出Android设备中的所有应用
    • adb shell pm list packages
    效果如下:
    在这里插入图片描述
    确认这些包名里面有你需要的应用的包名,可以把这些包名复制到记事本,然后按搜索来查找是否有自己需要的应用的包名。关于如何知道需要的应用的包名是什么,可查看文后的“获取运行在最前面的应用的包名”章节。
  2. 查看自己需要的应用的保存路径,假设想要查看的应用包名为:rst.rst3.hc_client,操作如下:
    • adb shell pm path rst.rst3.hc_client
    执行这个命令后,就能看到rst.rst3.hc_client包名的应用的保存位置了,如下:
    在这里插入图片描述
    这里的保存位置在/data/app/目录下,在这个目录下的apk都是属于系统apk的。
  3. 获取apk,在上一步中,我们已经查到了所需要apk的保存位置,复制这个路径,然后操作如下:
    • adb pull /data/app/rst.rst3.hc_client-1/base.apk
    执行效果如下:
    在这里插入图片描述
    这说明我们已经成功的把apk保存到电脑中了,上面的命令中我们没有指定保存的路径,则默认会保存到当前位置,上面命令行中的当前位置为Even,所以我们在Even目录中就能看到刚刚获取的名为base.apk的应用了,用压缩软件把apk解压,然后就可以获取到里面的资源文件了,像音频类型的资源,一般会保存在asserts目录中,或者是保存在res/raw目录中。
    通过这种方式,不但能获取普通的应用,就连系统应用也是可以获取到的。比如在这个示例中,/data/app/目录中保存的就是系统应用。

获取运行在最前面的应用的包名

如何知道一个未知应用的包名,方法是我们可以把未知包名的应用运行起来,且让它运行在最前面。然后我们可以写一个程序来检测运行在最前面的应用的包名,在我的一个项目中,有一个检测当前运行在最前面的程序的服务类,如果检测到最前面的程序不是我们的app时,就会把自己的app运行在最前面,比较流氓。这里我就直接把代码复制过来了(目前在Android 7.1上测试是OK的,在更高的版本不知道是否还可以),代码如下:

  • /**
  • * 栈顶app检查
  • */
  • class StackTopAppCheckService : Service() {
  • private lateinit var powerManager: PowerManager
  • companion object {
  • var needMoveToTop = true
  • }
  • override fun onBind(intent: Intent): IBinder? = null
  • private var run = false
  • override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
  • if (run) {
  • // 如果检查任务已经在运行了,则直接返回
  • return super.onStartCommand(intent, flags, startId)
  • }
  • run = true
  • val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
  • thread {
  • try {
  • while (run) {
  • checkStackTopApp(activityManager)
  • Thread.sleep(6000) // 每6秒钟检测一次
  • }
  • } catch (e: Exception) {
  • Timber.fw(e, "检查App是否在栈顶时出现异常")
  • }
  • Timber.fi("while循环执行结束")
  • // 恢复变量
  • run = false
  • }
  • return super.onStartCommand(intent, flags, startId)
  • }
  • private fun checkStackTopApp(activityManager: ActivityManager) {
  • if (!isRunningForeground(activityManager)) { // 如果不在栈顶,则移到栈顶
  • Timber.fw("我们的应用不在栈顶,当前栈顶应用为:${getStackTopAppPackageName(activityManager)},needMoveToTop = $needMoveToTop")
  • if (needMoveToTop) { // 有时候不希望一直弹到前台,则会把此变量设置为false
  • moveToStackTop(activityManager)
  • }
  • }
  • }
  • fun getStackTopAppPackageName(activityManager: ActivityManager? = null): String {
  • val manager = activityManager ?: getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
  • return manager.runningAppProcesses?.find {
  • it.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
  • }?.processName ?: "未知"
  • }
  • /** 把执法仪移动到栈顶 */
  • @Suppress("DEPRECATION")
  • private fun moveToStackTop(activityManager: ActivityManager) {
  • activityManager.getRunningTasks(100)?.find { it.topActivity?.packageName == App.getContext().packageName }?.let {
  • activityManager.moveTaskToFront(it.id, 0)
  • }
  • }
  • /** 判断本应用是否已经位于最前端:已经位于最前端时,返回 true;否则返回 false */
  • private fun isRunningForeground(activityManager: ActivityManager): Boolean {
  • return activityManager.runningAppProcesses?.any {
  • it.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
  • && it.processName == App.getContext().applicationInfo.processName
  • } ?: false
  • }
  • override fun onCreate() {
  • super.onCreate()
  • Timber.fi("onCreate")
  • powerManager = App.getContext().powerManager
  • }
  • override fun onDestroy() {
  • super.onDestroy()
  • Timber.fi("onDestroy")
  • run = false
  • }
  • }
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门