逆向:最近大火的 ChatGPT 客户端是如何实现的?

前言

这两天在 B 站刷视频,看到了 ChatGPT 新出的语音对话(如:炸裂更新!亲测GPT4语音交互,几十门语言都达到母语水平,外语老师危险了),非常惊叹。不得不说,OpenAI 不出手则已,一出手则一鸣惊人。那我作为一个 Android 学习者,却也不免想到了一个别的问题:作为新的 App,ChatGPT 的 Android 端是用什么写的呢?

安装试一下

ChatGPT Android 版目前可以在 Google 商店直接下载,这需要 Google 服务的支持。部分 Android 设备自带的有(比如小米,可以在设置里,搜索“谷歌”或者“Google”找到对应项开启)。当然,使用 GP 需要你有一个外区的 Google 账号,具体细节略过不谈。搜索 ChatGPT,排名第一的就是

Screenshot_2023-10-05-22-52-58-583_com.android.vending.jpg

下载完成后点击打开,登录你的账号即可。如果出现

Something went wrong. Please make sure your device has the latest version of Google Play.

就去 ApkPure 下载一个最新的 下载Google Play Store (有必要的话,再加上 下载Google Play服务),就能顺利登陆了。

具体使用不是重点,直接略过。接下来尝试看看本篇的主题吧

一些依赖

使用 LibChecker 查看此应用的基本信息,如下:

基本信息Activity

Screenshot_2023-10-05-23-28-52-581_com.absinthe.libchecker.jpg

Screenshot_2023-10-05-23-16-06-580_com.absinthe.libchecker-edit.jpg

一些关键的依赖如下:

  • Kotlin 1.9.10
  • AGP 8.1.1
  • Jetpack Compose 1.5.1
  • compileSdk 34
  • targetSdk 33

这个依赖版本可以说非常之新了,我相信读者如果是 Android 开发,所经手的 Android 项目基本没有能达到这种崭新程度的(如果有的话,也可以在评论区提一嘴,让我也震惊一下)。

App 的关键 Activity 只有两个,一个 MainActivity 承载了各种页面;另一个 VoiceModeActivity 应该就是上面视频里演示的语音模式。其实到这里,已经可以很大程度的猜想,这个应用是 Compose 应用了。不过单靠猜肯定不够,接下来我们继续探索一下

查看页面布局

东芝写的 “开发者助手”(这里本来有个链接的,但它在酷安被下架了,我也找不到了)里有一个“界面布局分析”的功能。可以看到每个 Widget 的基本信息。打开之后可以通过 Slider 或者音量键选择指定控件

Screenshot_2023-10-05-23-24-07-238_com.toshiba_dealin.developerhelper.jpg

虽然不能帮助直接获取到是否是由 Compose 编写的,但它能额外提供一些信息。比如,如果我们聚焦到一个文本上,你会发现这个文本是没有 ID 的

Screenshot_2023-10-05-23-23-42-465_com.toshiba_dealin.developerhelper-edit.jpg

很显然,在传统 View 体系中,基本上都是通过 ID 找到对应控件,然后进行各种操作的。而类似于 Jetpack Compose 这种框架则是直接改变对应 State,以触发对应 UI 更新,因此不需要 ID。到这里,我们就进一步确定了。

另一个可以佐证的部分是,当选择的控件是整个列表时,此处显示的类仍然只是 View,而非 RecyclerView 或者 ListView。这是因为,在 Jetpack Compose 中,显示列表用的是 LazyList,例如,一个对话列表的代码可能是:

@Composable
fun ChatList() {
   LazyColumn {
       items(chatList) {
           if (it.sendByMe) SendByMeItem(it)
           else SendByBotItem(it)
       }
   } 
}

简洁。轻快。

当然,这样仍然有问题,比如“开发者助手”的这个功能在某些场景下是工作不正常的,找不到对应 ID。所以接下来我们试着看看代码

反编译代码

通过 MT管理器 提取出 apks 文件,再进一步解压获得 apk 文件,我们就可以尝试对它反编译。这里有很多工具链可以选,比如手机端的 MT管理器自己(需要 VIP)、NP管理器(旧版免费、新版收费);PC 端的 ApkTool + dex2jar + jd-gui 三件套,或者 JADX 等。为了方便,在这里我们选择 JADX 一键完成。下载 Releases · skylot/jadx 后拖动 Apk 进去,等待即可

完成反编译后,我们可以搜索找到 MainActivityVoiceModeActivity,发现两个的代码都很简短,区区几十行。虽然代码混淆了导致反编译出来很难看懂,但共同点是,它们都调用了 j.a 方法。

image.png

image.png

查看此方法的具体代码,一个熟悉的字眼映入眼帘:Composition!而它是 Jetpack Compose 中的重要概念。从这个方法的代码也可以确定,j.a 方法实际上是 ComponentActivity.setContent(content: @Composable () -> Unit) 拓展函数,它是 Jetpack Compose 在 Android 平台的入口~

image.png

顺带一提,这个方法原始长这样:

public fun ComponentActivity.setContent(
    parent: CompositionContext? = null,
    content: @Composable () -> Unit
) {
    val existingComposeView = window.decorView
        .findViewById<ViewGroup>(android.R.id.content)
        .getChildAt(0) as? ComposeView

    if (existingComposeView != null) with(existingComposeView) {
        setParentCompositionContext(parent)
        setContent(content)
    } else ComposeView(this).apply {
        // Set content and parent **before** setContentView
        // to have ComposeView create the composition on attach
        setParentCompositionContext(parent)
        setContent(content)
        // Set the view tree owners before setting the content view so that the inflation process
        // and attach listeners will see them already present
        setOwners()
        setContentView(this, DefaultActivityContentLayoutParams)
    }
}

到此结束!这就是文章开头的结论来源,我们基本可以肯定,此 App 是用 Jetpack Compose 完成的 UI 部分。

别的细节

其实仅看 UI ,我也基本确定了这是 Jetpack Compose 写的。比如,它的菜单背景色是 Material You 中的颜色(而不是纯白)。

Screenshot_2023-10-05-23-25-49-334_com.openai.chatgpt-edit.jpg

由于 Jetpack Compose 的 material3 系列控件是在 Material You 设计规范出了之后才逐步完善起来的,因此它从诞生之日起就遵循着相应规范,在很多细节上有比较好的诠释。我自己的开源应用 译站 也是用的 Compose + MY,因此打开应用就感觉对味儿了。

做个对比

同样是新应用,而且都是新的 AI 应用,文章的最后我们不妨挑一个别的对比一下。我们这里选择了文心一言

叠甲:选择文心一言并不出于任何其他原因考量,单纯因为我本机上安装的有。本人下列的陈述仅从技术角度出发,仅作为技术交流和学习使用。本人无任何恶意贬低、歪曲之意。

同样是 LibChecker ,我们来看看文心一言的情况

基本Activity

Screenshot\_2023-10-05-23-29-13-726\_com.absinthe.libchecker.jpg

Screenshot_2023-10-05-23-29-25-401_com.absinthe.libchecker.jpg

作为对比还是很有意思的,虽然是新项目,但能感受到很多历史沉淀的气息。唯二被标注的分别是 Kotlin 1.6.21RxAndroid 1。它直接包含 61 项 Native Libraries,Activity 更是达到了 330 个之多(虽然绝大部分都是为了插件化和动态能力预留的)。当然也要指出,文心的功能比 ChatGPT Android 多很多,比如社区、发现版块,比如语音朗读回答,比如自定义角色等。

结尾

本文大概展示了一些技术,可能可以用来判定一个 App 的部分技术栈。除此之外也从侧面回答一个很多人疑惑:Jetpack Compose 真的有人用吗?事实是,有。不过大多数集中在国外。举个栗子,除了本文提到的,最近对标 X 的 Threads 也是基于 Jetpack Compose 构建的,国内的不少公司也有相关探索。
Compose 有什么优点?实话说,只要你上手写过,就能感受到它的简洁;那有缺点吗?不得不承认,有。一是对各项依赖较为严苛的要求(AGP、Gradle、Kotlin、甚至 AS 都要是比较新的版本),在非常旧的项目中集成有一定难度;二是性能目前仍然有差距。这也是 Compose 团队一直在尝试攻克的点,而相比最初的 1.0,其实已经有很大进步。总的来说,还是可以期待一下的。

学习 Compose -> Compose 中文社区文档:compose.funnysaltyfish.fun/ 或 官方文档:developer.android.google.cn/jetpack/com…

作者:FunnySaltyFish
链接:https://juejin.cn/post/7286632584149581885
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值