公司有个Android设备,里面内置了一款厂家自带的应用,该应该里面有一些提示语音,我想要把厂家的应用提取出来,以便获取应用内的语音资源,于是安装了一个APK Extractor,但是这个应用里没有列出来我需要的应用,系统应用也显示了,就是没有显示我需要的那个应用。经过百度,找到了另一种提取方式,成功的提取到了我需要的apk。
-
通过adb命令列出Android设备中的所有应用
adb shell pm list packages
效果如下:
确认这些包名里面有你需要的应用的包名,可以把这些包名复制到记事本,然后按搜索来查找是否有自己需要的应用的包名。关于如何知道需要的应用的包名是什么,可查看后面的“获取运行在最前面的应用的包名”章节。 -
查看自己需要的应用的保存路径,假设想要查看的应用包名为:rst.rst3.hc_client, *** 作如下:
adb shell pm path rst.rst3.hc_client
执行这个命令后,就能看到rst.rst3.hc_client包名的应用的保存位置了,如下:
这里的保存位置在/data/app/目录下,在这个目录下的apk都是属于系统apk的。 -
获取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的,在更高的版本不知道是否还可以),代码如下:
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) { // 有时候不希望一直d到前台,则会把此变量设置为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) } } 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 } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)