在APK中获取鸿蒙应用Ability信息

2023-05-16

Android开发工具箱大概在版本2.2.0(2021-06-10)就已经支持查看鸿蒙系统信息以及鸿蒙应用信息了。这里我讲一下Android开发工具箱是如何在Android应用中(APK)获取鸿蒙应用Ability信息(类似于Android应用的四大组件信息)

Android开发工具箱可在应用宝、酷安下载,微信公众号:Android开发工具箱

https://www.coolapk.com/apk/com.su.assistant.pro

Android中,我们获取应用列表之后,再获取应用的PackageInfo实例即可获得四大组件列表,在鸿蒙中,我们获取到通过IBundleManager获取到Ability列表即可。IBundleManager类似Android中的PackageManager,在Android中,我们通过Context即可获取PackageManager,在鸿蒙中,通过ohos.app.Context也同样可以得到IBundleManager。

鸿蒙中的ohos.app.Context从何处来,根据我的Android的开发经验,我首选Application。

鸿蒙系统中也有一个Application,此Application并非Android中的android.app.Application,而是ohos.app.Application

整理一下步骤,我将尝试依次获取如下类型的实例:

  1. ohos.app.Application

  2. ohos.app.Context

  3. ohos.bundle.IBundleManager

我们知道在鸿蒙中有ohos.abilityshell.HarmonyApplication,它是继承android.app.Application,所以它只是一个Android中的普通的Application。HarmonyApplication源码是公开的,我在里面发现了这个:

private ohos.app.Application application = new ohos.app.Application();

但是,在Android系统中是没有这个东西的,所以我们无法直接的在Android系统get一个ohos.app.Application对象。不过,我们可以尝试构造一个ohos.app.Application对象。这里要注意的是,我们也没有办法直接引用这个类,因为鸿蒙并没有公开相应的代码,所以只有反射咯。

实例化Application很简单,就是调用一个无参的构造函数即可

val applicationContext = context.applicationContext
val classLoader = applicationContext.classLoader
val clazzOhosApplication = Class.forName("ohos.app.Application")
sOhosApplication = clazzOhosApplication.newInstance()

此时我们可以通过sOhosApplication利用反射拿到ohos.app.Context

可惜,事情到这里并没结束,我们通过ohos.app.Context获取IBundleManager依然返回null。我猜测是初始化ohos.app.Application的时候出了问题

接下来继续在HarmonyApplication里面找线索,由于里面用了很多闭源的类,所以在阅读的时候造成了很大障碍,最终,我在下面的函数中找到了线索


private void attachHapModuleContext(AbilityContext harmonyAbilityPackage, HapModuleInfo hapModuleInfo) {
    if (harmonyAbilityPackage != null) {
        ContextDeal deal = new ContextDeal(getApplicationContext(), getClassLoader());
        ...
        deal.setApplication(this.application);
        ...
    }
    harmonyAbilityPackage.attachBaseContext(deal);
}

为了方便阅读,我把无关的代码删除了。上面if中的逻辑和初始化ohos.app.Application是相关的,所以利用反射复制一遍上述代码的逻辑

private fun initApplication(context: Context) {
    val applicationContext = context.applicationContext
    val classLoader = applicationContext.classLoader
    try {
        val clazzOhosApplication = Class.forName("ohos.app.Application")
        sOhosApplication = clazzOhosApplication.newInstance()
        val clazzContextDeal = Class.forName("ohos.app.ContextDeal")
        val contextDealConstructor = clazzContextDeal.getConstructor(
            Context::class.java, ClassLoader::class.java
        )
        val contextDeal = contextDealConstructor.newInstance(applicationContext, classLoader)
        val setApplicationMethod =
            clazzContextDeal.getDeclaredMethod("setApplication", clazzOhosApplication)
        setApplicationMethod.invoke(contextDeal, sOhosApplication)
    } catch (e: Throwable) {
        Log.w(TAG, e)
    }
}

然后再次运行,遗憾的是,此时我们通过ohos.app.Context获取IBundleManager依然返回null。

在attachHapModuleContext方法中的最后执行了AbilityContext.attachBaseContext(ContextDeal),可惜AbilityContext也没有开源,我们无法知道AbilityContext.attachBaseContext(ContextDeal)里面做了什么。

不过,我发现ohos.app.Application是继承AbilityContext的(反射打印一下便知),将上面的代码修改一下,调用一下attachBaseContext

private fun initApplication(context: Context) {
    val applicationContext = context.applicationContext
    val classLoader = applicationContext.classLoader
    try {
        val clazzOhosApplication = Class.forName("ohos.app.Application")
        sOhosApplication = clazzOhosApplication.newInstance()
        LogUtil.logParents(clazzOhosApplication)
        LogUtil.logClassMethods(clazzOhosApplication)
        val clazzContextDeal = Class.forName("ohos.app.ContextDeal")
        val contextDealConstructor = clazzContextDeal.getConstructor(
            Context::class.java, ClassLoader::class.java
        )
        val contextDeal = contextDealConstructor.newInstance(applicationContext, classLoader)
        val setApplicationMethod =
            clazzContextDeal.getDeclaredMethod("setApplication", clazzOhosApplication)
        setApplicationMethod.invoke(contextDeal, sOhosApplication)
        val attachBaseContextMethod =
            clazzOhosApplication.getMethod("attachBaseContext", ohos.app.Context::class.java)
        attachBaseContextMethod.invoke(sOhosApplication, contextDeal)
    } catch (e: Throwable) {
        Log.w(TAG, e)
    }
}

再次尝试获取IBundleManager,这次终于成功了,我们有了IBundleManager实例。

在Android中,我们获取四大组件信息就要先获得PackageInfo,然后再获取组件信息

packageInfo.activities
packageInfo.receivers
packageInfo.services
packageInfo.providers

在鸿蒙中,我们获取BundleInfo,从BundleInfo中可直接获得AbilityInfo,但是要注意的是,只有鸿蒙应用才有bundleInfo,鸿蒙系统安装apk文件是没有bundleInfo的,返回结果为null

fun getBundleInfo(bundleName: String, flags: Int): BundleInfo? {
    try {
        return mIBundleManager!!.getBundleInfo(bundleName, flags)
    } catch (e: RemoteException) {
        Log.w("IBundleManagerDelegate", "bundleName: $bundleName", e)
    }
    return null
}

为了方便大家测试,这里告诉大家华为远程模拟器P40中

  1. com.huawei.email是鸿蒙应用

  2. com.sina.weibo是Android应用(可在华为市场下载鸿蒙版微博)

然后,程序又挂了...我们还需要一个权限:


<uses-permission android:name="ohos.permission.GET_BUNDLE_INFO" />

接下来再获取BundleInfo就可正常获取了

ohosContext!!.bundleManager!!.getBundleInfo(bundleName, flags)

想要查看鸿蒙系统中哪些是鸿蒙应用,可以使用Android开发工具箱的应用统计功能(PRO),其中一项为应用类型统计。

鸿蒙应用中所有组件信息都为AbilityInfo类型,通过type(AbilityInfo.AbilityType)来区分组件类别。至此,我们拿到了AbilityInfo实例,也就是拿到了组件所有信息了。

获取系统信息就简单了,下面是获取版本信息


SystemVersion.getVersion()

SystemVersion还可以获取其他信息,这里就不再列举了

最后,我将此部分代码贡献给了开源应用LibChecker - https://github.com/zhaobozhen/LibChecker

LibChecker是一个查看并分析App使用的第三方库的应用。提供了一些基本功能:App的ABI架构查看和统计、原生库的查看、四大组件查看,除此之外还对知名库进行标记、统计等。也欢迎大家试用

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在APK中获取鸿蒙应用Ability信息 的相关文章

  • 我如何知道模拟器上运行的应用程序是否是最新版本?

    我使用 Eclipse 和 Android 模拟器开发 Android 应用程序 有时我不知道我是否在模拟器中运行最新版本的应用程序 有什么办法可以检查是否是最新版本吗 例如 我对应用程序的布局进行了更改 但是当我在模拟器中运行应用程序时
  • 在 APK 文件中嵌入登录详细信息,每个用户都不同(或其他选项?)

    我们被要求为一家拥有现有网站和现有用户的公司创建一个 Android 瘦 Web 客户端 他们想要向用户发送彩信 为每个用户提供自己的下载 URL 该 URL 将指向专门为该用户创建的 Android apk 文件 它将包含该用户的网站登录
  • Android 2.3.4 上出现“应用程序未安装”错误

    我有一个程序在 Android 模拟器中运行 我时不时地创造一个 apk并将其导出到我的索尼爱立信 Xperia积极测试 我面临着错误应用程序未安装 我尝试过重新启动手机并删除现有的 apk 不修复故障
  • Android - 如何拦截“安装应用程序”意图

    好吧 所以不完全确定这是可能的 但尝试编写一个应用程序 以便我可以在执行以下任何活动之前运行一些代码 1 从网络下载 APK 并启动安装程序 2 在android市场上按下安装按钮 是否有可能拦截并提示这些事件 或者谷歌已经将这些东西锁定得
  • Android 中失败 [INSTALL_FAILED_USER_RESTRICTED:无效的 apk]

    我使用的是Android Studio 3 0 1 当我尝试运行应用程序时 INSTALL FAILED USER RESTRICTED 无效的 apk 发生错误 我还禁用了即时运行 我再次运行应用程序 但出现同样的错误 04 04 10
  • 权限拒绝:打开提供程序 android.support.v4.content.FileProvider

    我在尝试在 Android 模拟器中执行应用程序升级时遇到了一些问题 场景的流程来自一个 Activity 我将执行异步任务A哪个打开片段A 然后在里面异步任务A 我会检查是否有版本升级 如果可用并且用户选择了 确定 片段A 我将继续异步任
  • 当最小 SDK 从 21 增加到 24 时,APK 大小增加了 35mb

    最近 我们将支持的最小 SDK 从 API 21 提高到了 24 显然 这一变化导致我们的 APK 大小从 65mb 增加到 103mb 从Android studio中的APK分析中 我们可以看到所有的 so文件的大小基本上都增加了一倍
  • 对 Android APK 进行逆向工程以获取代码? [复制]

    这个问题在这里已经有答案了 可能的重复 Android 从 APK 文件获取源代码 https stackoverflow com questions 3593420 android getting source code from an
  • 如何构建没有声音空安全的APK

    我可以在手机上以发布模式运行应用程序并传递标志 no sound null safety release 但 两者都不flutter build apk enable experiment non nullable nor flutter
  • Google Play 定时发布

    在 Google Play 上使用 定时发布 更新应用程序时 上传 APK 后 是否应该选择 立即发布到生产环境 选项 这会将新的 APK 提交到生产环境吗 还是 Google Play 会直接处理它并等待我点击 上线 Google 或其他
  • Android Studio 3.1.1 更新后,“定位”链接无法打开生成的 APK 文件夹

    更新 Android 3 1 1 更新后出现问题 APK 生成过程完成后 Android Studio Windows 操作系统 会弹出一个窗口来定位或分析 APK 不幸的是 如果我点击locate 什么也没有发生 UPDATE 在 APK
  • 重命名 APK 内的包名称

    我创建了一个AIR app目前市场上有这种产品 要更新应用程序 显然我必须保留相同的包名称 我的第一个版本是使用以下方式打包的Eclipse使用 ADT 插件 现在可以使用AIR 3 0 本机扩展 ANE 当我第一次开发该应用程序时不可用
  • 如何在没有 Eclipse 的情况下构建 apk 或使用配置文件修改 apk 构建?

    我想从 xml 文件构建一个具有一些大型配置的 apk 我想知道是否有任何方法可以控制 apk 的构建过程 或者是否有任何方法可以根据我们的配置 xml 文件对我们的源进行一些修改 从我们的源创建 apk 或者任何其他方式来构建apk文件
  • 当更新可用时,手动安装的 apk(不是从 Play 商店)会收到通知吗?

    我想在平板电脑上安装 apk 知道怎么做 我的平板电脑会收到来自 Play 商店的通知吗 该更新已在 Play 商店中准备就绪 我应该安装它吗 仅当满足以下两个条件时 您才会收到更新 在 Google Play 已安装的应用程序 选项卡中看
  • Android 密钥库停止工作

    就在最近 我在密钥存储方面遇到了问题 我知道已经有很多关于这个问题的问题了 我已经阅读了所有这些内容并疯狂地用谷歌搜索 Error keytool error java io IOException Keystore was tampere
  • 无法加载(查找)j2v8_android_x86 库

    我有一个使用的 gradle 项目j2v8 android 2 2 1 http mvnrepository com artifact com eclipsesource j2v8 j2v8 android 2 2 1库 为 V8 JS 引
  • 配置根项目“firebase_auth”时出现问题

    my error 我无法构建 apk 发布文件 我完成了应用程序一段时间 没有出现错误 几天后 我在构建应用程序时收到此错误 请告诉我如何摆脱它 我尝试了 4 个小时 什么也没得到 FAILURE Build failed with an
  • Android构建apk:控制MANIFEST.MF

    Android 构建 APK 假设一个 apk 包含一个库 jar 例如 foo jar 该库具有 META INF MANIFEST MF 这对于它的运行很重要 但在APK中有一个包含签名数据的MANIFEST MF 并且lib jar
  • Google play APK 上传错误重复权限声明

    我尝试上传新的 apk 使用我自己的发布密钥存储签名 并在 google play 开发者控制台中收到以下错误 重复的许可声明 android permission ACCESS COARSE LOCATION 与不同 maxSdkVers
  • Meteor:即使设置了 ANDROID_HOME 也未设置

    操作系统 Ubuntu 14 04 框架 流星1 1 0 2 应用名称 Songofy 这是输出meteor install sdk android meteor install sdk android Found Android bund

随机推荐