Android 与 Chrome OS 中针对大屏幕设备的更新

Android 与 Chrome OS 中针对大屏幕设备的更新

随着智能终端硬件的不断革新,大尺寸设备的种类越来越丰富,比如手机、折叠屏设备、平板电脑、ChromeBook、外接显示器的 ChromeBox 和集成屏幕的 Chromebase 等。Google 团队正在将更多研发精力投入到 Android 框架、Jetpack 和 Chrome 操作系统中。

△ Android 12L 和 Jetpack 增加了新的 API 和功能,使您的 APP 外观更精美,功能更强大。

△ Android 12L 和 Jetpack 增加了新的 API 和功能,使您的 APP 外观更精美,功能更强大。

请继续阅读,查看 Android 系统和 Chrome OS 对大屏幕设备的支持的更新!

如果您更喜欢通过视频了解此内容,请在此处查看:

△ Android 与 Chrome OS 中针对大屏幕设备的更新

Android 12L

如下图所示数据可以发现,用户对更大屏幕空间的需求在不断增长,仅 2020 年一年 Android 平板电脑的销量增加 1 亿台,Chrome 操作系统增加超 92%。目前在使用的大屏幕 Android 设备超过 2.5 亿,所以这就需要应用针对这类设备进行相应的适配。为了能够适应日益增长的设备数量和用户需求,我们推出了针对大屏幕设备的 Android 12L (下文简称 12L)。

△ 大屏幕设备正在逐步成为主流 1 亿新增 Android 平板电脑数据来源: 2021 年第二季度: IDC 单季度个人计算设备跟踪

△ 大屏幕设备正在逐步成为主流 1 亿新增 Android 平板电脑数据来源: 2021 年第二季度: IDC 单季度个人计算设备跟踪

一直以来,我们都与开发者紧密合作,及时了解他们针对大屏幕开发的需求以及上游设备制造商的实时动向,并行改进功能和 API,这些更新将在 2022 年初落地,使 Android 12 能够更好地运行在这些大屏幕设备上。12L 包含多个专门针对开发者的优化,包括更出色的多任务处理,重新设计的外观以充分利用屏幕空间,同时还增加了兼容模式,以确保在小屏幕手机上也可以正常运行。

多任务处理

从 Android 12 开始多任务处理已经成为日常操作,所有应用均可以在多窗口模式下运行。但是需要注意的是应用可能以分屏模式运行或以窗口形式出现在另一个应用旁边。

在以下场景中尤其要注意:

  1. 自行渲染界面元素或需要特定的窗口尺寸;
  2. 应用需要访问独占硬件设备,比如摄像头和麦克风。

多窗口模式

△ 多窗口支持相较之前更易访问

△ 多窗口支持相较之前更易访问

为了支持多任务处理,Android 12L 更新了界面,包括经过改进的供应用切换的任务栏。我们都知道过去用户要进入分屏模式的操作比较繁杂。全新的任务栏简化了应用之间的快捷切换方式,并且可以轻松返回主屏幕。

导航按钮

△ 三按钮导航相较之前更易访问

△ 三按钮导航相较之前更易访问

在屏幕较大的设备上,任务栏可以很方便地将应用转为分屏模式或者多窗口模式。这是因为所有应用无论是否声明尺寸可切换,都可以在分屏模式或者单独窗口下运行,所以有必要更新您的应用以适配尺寸变化,同时避免应用重启或者进入兼容模式。任务栏还将三按钮式导航栏移至屏幕一侧,以方便用户手持大屏幕设备操作。

系统界面

△ 系统界面 — 现代化的外观和质感

△ 系统界面 — 现代化的外观和质感

Android 12L 还带来了多项系统界面相关的用户界面更新。包括优化主屏幕布局,大幅调整通知外观和风格,加入了弹出窗口,使 PIN 码输入更加简单。您无需采取任何操作就可以在应用中自动采用新的系统外观。此外,我们还在更新设置、设置向导等系统应用,从而更好地利用屏幕空间。

改进的任务栏

△ 优化体验后的任务栏 — 为了更好的应用切换体验

△ 优化体验后的任务栏 — 为了更好的应用切换体验

为了能够提升应用切换的体验,我们优化了任务栏。用户可以快速实现应用切换、回到主屏幕等操作。在屏幕较大的设备上,任务栏可以拖动应用进入分屏和多窗口模式。

兼容模式

△ 兼容模式 — 稳定性和视觉提升

△ 兼容模式 — 稳定性和视觉提升

如果您的应用锁定为横向或者纵向模式,并且无法调整大小,那么当用户进入分屏、打开折叠设备,亦或是在 ChromeOS 那样的多窗口环境下,应用也能以兼容模式显示。从而确保应用外观和功能能够按照最初的效果呈现。

我们正在更新功能和兼容模式下的样式和呈现效果,虽然这些可以使用户继续使用那些不可改变尺寸的应用,并且也能够和系统相契合,但是仍然无法提供理想的用户体验,而是否对应用做出优化的决定权在您手上。

Play 商店更新

△ Play 商店更新 — 展示适配大屏幕的应用

△ Play 商店更新 — 展示适配大屏幕的应用

我们还针对 Play 商店做出了一些改进,帮助用户找到适合大屏幕的最佳应用。

首先,我们正在将大屏幕设备应用的评分和评论功能独立出来;其次,我们正在针对应用的可变尺寸的功能和大屏幕上的布局方面,优化我们的质量检验流程;最后,我们将对输入的支持以及其他针对大屏幕的功能进行研究。通过这些途径,我们就能为用户挑选出能够面向他们的设备提供最佳体验的应用。我们计划在 2022 年推出这些改进届时大家可以更加详细地了解这部分内容。

如需要更多资料,请参阅如下文章:

Android 12L 的可折叠屏模拟器

△ Android 12L/可折叠模拟器 developer.android.google.cn/12L

△ Android 12L/可折叠模拟器 developer.android.google.cn/12L

12L 功能投放包含全新 API 以及新的 SDK 级别,即 32 级,方便您快速定位新功能。请注意,Play 商店每年增加目标 SDK 的要求,仅适用于 Android 12,即 SDK 31,不会强制要求您升级为 32。

今天就开始测试这些新功能和 API 吧,获取 Android 12L 开发者预览版,让您的应用准备好迎接即将发布的公开版本。您也能在 Android Studio 模拟器 中使用 12L 系统映像,尝试分屏、折叠和旋转事件。确保应用在整个用户使用过程中都能保持美观。

很快大家就能使用 Lenovo P12 Pro、Samsung Galaxy Z Fold 3 测试这些功能。12L 功能的更新振奋人心,我们也期待着在今后的 Android 版本中加入更丰富的功能以及对大屏幕设备更多的支持,我们将继续努力让 Android 成为更好的操作系统,为用户和开发者提供更优质的服务。

Jetpack WindowManager

Jetpack WindowManager 是提供向后兼容 API 的库,能够适配窗口规格和尺寸,还能提供关于显示功能详细信息,比如折叠、铰链和设备配置。本文将会讲解库中可用的稳定 API,还会介绍当前和未来版本中的一些全新实验工具从而让您的应用在大屏幕上显得美观。该库采用了 12L 的最新功能,但也兼容之前平台版本,低至 API 级别 14。

WindowMetrics

△ 为任意屏幕尺寸构建 Android 界面

△ 为任意屏幕尺寸构建 Android 界面

首先介绍 WindowMetrics。Android 11 引入了一套新的 WindowManager API,能够给出应用当前运行窗口的准确测量数据。在大屏幕设备上,由于用户对于分屏和其他多窗口形式的使用频率越来越高,您的应用很可能不会占据整个屏幕。在 Samsung Galaxy Z Fold 系列手机中,我们发现其在分屏使用率上高达七倍于其它手机的现象。另一个例子是当大屏幕手机处于不同方向时,窗口带有黑边。使应用能够在尺寸上完全可变是非常重要的,我们会大篇幅来讨论这个主题。

那么如何确定 Activity 的尺寸呢?

class MyActivity : Activity() {

        override fun onConfigurationChanged(newConfig: Configuration) {
            super.onConfigurationChanged(newConfig)
            val windowMetrics = WindowMetricsCalculator.getOrCreate()
                .computeCurrentWindowMetrics(this)
        }
}

WindowMetrics API 可以在所有可能的状态下返回窗口的准确像素尺寸,而且向下兼容至 SDK 级别 14。如果用户扩展了应用的显示,它还会提示您可配置的最大尺寸,以便开发者选择合适的资源提前加载。请记住,WindowMetrics 可在运行时更改,因此建议值更新时机为最初创建 Activity 的时候以及使用 WindowMetricsCalculator 更改配置的时候。请不要使用已经弃用的显示相关的 API,比如 "getRealMetrics" 或者 "getRealSize",否则您可能会得到异常的尺寸值。

WindowSizeClasses

在所有设备类型上都能够将应用直观呈现给用户的另一个关键要素是提供不同的布局。我们从大家的反馈中了解到在纷繁复杂的设备生态系统中,能够清楚地知道针对哪种屏幕尺寸进行开发是非常困难的。

△ Jetpack WindowManager 中的窗口尺寸类

△ Jetpack WindowManager 中的窗口尺寸类

现在 Jetpack 增加了 WindowSize 类,使得这一困难迎刃而解。该功能引入了独具特色的布局断点 (layout breakpoint) 可以帮助您了解如何适配界面。当需要针对不同的设备类型选择合适的布局时或者在多窗口模式下需要响应窗口的变化时,就需要用到 WindowSize 类。

之前在竖屏模式下,用户大多数时间仅仅操作一个应用,但是平板电脑通常是横屏模式。而对于可折叠设备和不同的多窗口模式,应用经常需要在单次会话中将窗口尺寸变大或者变小。所以需要满足尽量多的场景。如果您希望了解 WindowManager Jetpack 1.1 相关功能,请查阅我们的推文《为任意屏幕尺寸构建 Android 界面》。

可折叠屏幕

△ 可折叠屏幕

△ 可折叠屏幕

其中的创新潜力很大,特别是针对可折叠设备。随着市场上此类设备数量逐渐增加,您可以更进一步,不仅使应用能够兼容大屏幕,而且在应用正在运行的情况下,当用户折叠或展开设备时,应用能够适配设备不同的状态。

支持不同的模式能够为应用带来新的交互方式以及新的使用体验。例如,现在的可折叠设备常放置于桌面使用,非常适合观看视频或接听免提电话。设备的放置方式使屏幕的一部分处于舒适的观看角度,而屏幕的另一部分则放在平稳的台面上,使其非常适合各种交互元素。

FoldingFeature

△ FoldingFeature

△ FoldingFeature

我们来看看 API 库能为您提供哪些帮助。您可以使用 FoldingFeature 判断设备的姿态。该类用于监测可折叠设备的状态,并且使用特征类型、屏幕方向和状态更新界面在必要时更新周边的界面。

val windowInfoRepo = windowInfoRepository()
lifecycleScope.launch(Dispatchers.Main) {
    lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
        windowInfoRepo.windowLayoutInfo
            .collect { newLayoutInfo ->
                updateCurrentState(newLayoutInfo)
            }
     }
}

有两种可能的状态: 平开与半开。平开状态下屏幕完全展开成平面,但某些情况下屏幕依然被铰链分割而并非连续整体。而半开状态下,窗口始终包含至少两个逻辑区。功能布局信息通过 WindowInfoRepository 提供。要开始或停止监听事件,可使用生命周期作用域,在 Activity 可见时进行追踪。之后,您可以使用 windowLayoutInfo 对象中可用的信息更新应用布局。

private fun isTabletopPosture(foldFeature: FoldingFeature) =
    foldFeature.state == FoldingFeature.State.HALF_OPENED &&
        foldFeature.orientation == FoldingFeature.Orientation.HORIZONTAL

FoldingFeature 包含铰链屏幕方向和状态等信息。可使用这些值来判断设备是处于桌面模式,还是铰链平放的半开模式。如需了解更多详情,请查阅文档了解 折叠设备构建的完整指南

测试 WindowManager

为了长期保持此类新型布局简单易用,我们还在 JetpackWindowManager 加入了新的测试 API。还在库中引入专门的窗口测试模块。

val testFeature = FoldingFeature(
   activity: Activity,
   center: Int = -1,
   size: Int = 0,
   state: State = HALF_OPENED,
   orientation: Orientation = VERTICAL,
)

val expected = WindowLayoutInfo(listOf(testFeature))

这个示例展示了创建主要类相关的测试实例。注意 Activity 是 FoldingFeature 函数的唯一参数没有默认值。当前测试 FoldingFeature 的默认配置屏幕中间水平布局为半开状态。

private val activityRule = ActivityScenarioRule(TestActivity:class.java)
private val publisherRule = WindowLayoutInfoPublisherRule()

@get:Rule
public val testRule: TestRule

init {
  testRule = RuleChain.outerRule(publisherRule).around(activityRule)
}

WindowLayoutInfoPublisherRule 可用于测试界面以及界面如何响应 FoldingFeatures。可以将其关联至 ActivityScenarioRule。但是应用上架规则不能完全替代在设备上进行的端到端测试。比如,真实设备可能会更新屏幕方向窗口布局信息。但如果使用 publisherRule,就必须自行更新窗口尺寸和窗口布局信息。

@Test
public fun testMyFeature() {
  val feature = WindowLayoutInfo(emptyList())
  publisherRule.overrideWindowLayoutInfo(feature)

  activityRule.scenario.onActivity { activity ->
     //应用相关测试
  }
}

测试规则设置完成后,可使用 overrideWindowLayoutInfo 方法替换当前布局信息对象。

Activity 嵌套

我们认识到转换现有旧版代码库使其支持大屏幕可能困难重重。对于长期以来针对单一屏幕进行开发使用 Activity 的应用,通过 Fragments 或其他工具切换为多窗格布局可能需要大幅重构,消耗大量团队资源。为了使转换更加容易,我们推出了 ActivityEmbedding,这是一套 WindowManager Jetpack 功能集,可用于在目前主流大屏幕设备端灵活组织 Activity 窗口。

并排显示的 Activity

△ Jetpack WindowManager 中的 Activity embedding

△ Jetpack WindowManager 中的 Activity embedding

它的初版界面实现专注于通过在多列布局中并排显示 Activity 从而充分利用大屏幕空间。例如,您可以通过独立的 Activity 显示这些列表和详细信息,不过您可能希望在大屏幕上显示这些内容。虽然我建议您以单一 Activity 的方式重构应用,不过能理解,这么做的成本非常高。该功能让您能够利用现有应用结构来优化大屏幕布局。而且最令人兴奋的是采用该功能只需略微调整代码,某些情况下代码甚至无需调整。

△ 小屏幕和大屏幕

△ 小屏幕和大屏幕

我们来详细看一下。该功能在设计之初就考虑到兼容性。基于可用屏幕空间以及您提供的设置,库可以自动选择合适的展示类型,从而避免了分支应用内导航代码就能处理不同部分中的大小屏幕。该库还支持运行时屏幕和窗口尺寸变更,如果用户折叠或展开设备或在多窗口模式下重新调整窗口大小,展示将会自动更新,您无需额外操作。

Activity 堆栈

△ Activity 堆栈

△ Activity 堆栈

我们还会遵循应用中 Activity 的现有排序,识别每个分块中的主副、两个容器或 Activity 堆栈。副容器始终位于主容器之上。如果屏幕空间较小 Activity 堆栈还与平常一样;但如果空间足够,两个堆栈就可以并排显示。

下面通过示例展现如果副容器中有多个 Activity,会发生什么状况?

△ Activity 堆栈

△ Activity 堆栈

他们会自动出现在启动时的相同边界之内。现有的 Activity 启动和预期分辨率规则同样适用。

△ 多重深度层级

△ 多重深度层级

库还支持多层次导航,创建多个分块,最多显示两个窗格。开启新窗格时,之前创建的窗格将移至屏幕外。此示例中,如果现有分块显示 Activity A 和 B,而您需要将新的 Activity C 在一侧显示,则会创建第二个分块显示 B 和 C。同样,容器的 Z-Order 依然认为在顶部。

△ 屏幕尺寸变化

△ 屏幕尺寸变化

这样的顺序意味着用户关闭可折叠设备,继续使用应用时您可以重新调整容器的大小和位置保持 Activity 的顺序。副堆栈中的顶部 Activity 会自动扩展,但如果用户展开设备,可随时再次并排显示。

△ 占位符

△ 占位符

这是另一个不同的用例,我们称之为「占位符」。有时应用会在主页显示顶级导航列表,用户做出选择前没有辅助内容可显示。然而,为了充分利用可用空间,也出于一致性考虑,应该在应用开启后立刻显示分块,此时辅助内容大部分留空。同时,如果在较小的屏幕上开启应用,并且在设备折叠之后,我们不希望在顶部显示空白页。

我们在库中添加了一个专门的选项来支持占位符的使用场景,来一起看一下如何在应用中集成该功能。

分块规则

<SplitPairRule>
     <SplitPairFilter
         window:primaryActivityName=”.ActivityA”
         window:secondaryActivityName=”.AcitvityB” />
</SplitPairRule>

首先,在构建文件中声明库依赖;然后,在 assets 中创建一个 XML 文件并提供规则定义: 哪些 Activity 应该分块,以及分块的属性。

此示例中,当 B 在 A 之后被打开的时候,我希望把 Activity A 和 B 放入分块中。为了实现这一点,我使用默认配置添加了一个单独的分块配对规则,再加入一个过滤条件用于匹配 Activity 组件名称。Activity B 从 A 中启动后,会核对并匹配过滤器,并且库会自动创建新的分块。

我们针对不同的场景提供了不同类型的规则,从而给您一定的灵活性。您可以在我们的文档中找到更多的相关信息,另外,也可以使用运行时 API 按需添加或移除规则。

配置

接下来,我们需要将规则定义告知库。此示例中,我们使用的是 Jetpack AppStartup 库。此示例中,在其它上传组件和 Activity 启动之前,我们使用 Jetpack AppStartup 库进行初始化。要实现这一点,我们需要在构建文件中添加库依赖,并且在 AndroidManifest 中添加以下条目。这里我们指定所使用的 initializer 类。

<provider
    android:name=”androidx.startup.InitializationProvider”
    android:authorities=”${applicationId}.androidx-startup”
    android:exported=”false”
    tools:node=”merge”>
        <meta-data
            android:name=”example.SplitInitializer”
            android:value=”androidx.startup” />
</provider>

最后,添加 initializer 类的实现。如果您已经在应用中使用 AppStartup,那么应该比较熟悉这样的结构。

class ExampleWindowInitializer : Initializer<SplitController> {
    override fun create(context: Context): SplitController {
        SplitController.initialize(context, R.xml.main_split_config)
        return SplitController.getInstance(context)
    }

    override fun dependencies(): List<Class<out Initializer<*>>> {
        return emptyList()
    }
}

要设置规则,可向 SplitController.initialize 提供 XML 资源 ID 和定义。

大功告成!库将会追踪在您的代码库中不同位置启动的 Activity,检查所用到的 intent 以及启动这些 Intent 的 Activity,如果找到匹配规则,会创建新的分块,并由库进行管理。

在最新版的 WindowManager Jetpack 扩展的大屏幕设备上会提供该功能。

现在就能在 12L 模拟器中使用,而且很快就能在 Samsung GalaxyZ Fold 3 等真实设备上找到它。在不支持该功能的设备上显示方式还会和之前一样,Activity 仍然会堆叠显示,互相完全覆盖,因此无需担心尚未支持的设备会出现显示异常。

如果您需要知晓该功能是否可用,可使用专用的运行时 API。我们也在尝试其他与多屏显示设备相关的交互方式。具体实现代码,请参阅 WindowManager Jetpack Demo

后侧屏显示模式

△ 后侧屏幕显示模式

△ 后侧屏幕显示模式

一个酷炫的例子是后侧屏幕显示模式可在设备展开状态下,使用高质量主摄像头自拍的同时显示自拍预览画面。我们正在开发一套 API 支持此应用场景。您可在今后的版本的实验性 WindowManager Jetpack API 找到上述功能。

Chrome 操作系统

△ Chrome OS 优化

△ Chrome OS 优化

多年来,Chrome 操作系统让用户能够在大屏幕设备上安装和运行 Android 应用。

△ 画中画

△ 画中画

最近,我们针对 Android 应用体验进行了多方面改进,比如提升画中画支持、加入低延迟触控笔库,以及美化那些并非针对大屏幕设备设计的应用的界面。现在画中画在 Chrome 操作系统中界面更精美、运行更流畅。使用标准 Android 画中画 API 无需额外投入,即可获得最新外观和功能。

接下来我们来快速浏览一下这些 API。首先,在清单文件中指出画中画支持:

android:supportsPictureInPicture=”true”

然后通过 enterPictureInPictureMode 启动它:

pipButton.setOnClickListener {
    enterPictureInPictureMode(
      new PictureInPictureParams.Builder().build())
}

您还可以使用 onUserLeaveHint 实现 Activity 在被用户置入后台时,自动进入画中画模式等功能:

override fun onUserLeaveHint() {
    enterPictureInPictureMode(
      new PictureInPictureParams.Builder().build())
}

请注意,此模式下可能需要调整界面。如需进行调整,请找到 onPictureInPictureModeChanged 回调,并按需做出相应修改:

override fun onPictureInPictureModeChanged(
         isInPictureInPictureMode: Boolean,
         newConfig: Configuration) {
      if (isInPictureInPictureMode) {
          // 画中画功能实现
      } else {
          // 返回常规界面
      }
 }

2021 年 5 月我们宣布推出 Chrome 操作系统低延迟时间触控笔 API,尽量降低绘画应用的延迟。您可以立刻前往 GitHub 查看 API 和演示版应用。

兼容性模式

△ 兼容性模式

△ 兼容性模式

在大屏幕平板电脑 Chromebook 或外接显示器上运行仅针对小尺寸竖屏 Android 手机设计的应用时,如果拉伸进入全屏视图,那么应用外观和性能可能会差强人意。应用可能出现各种问题,包括布局欠佳,以及应用因为无法正确处理多窗口或尺寸调整事件而发生的崩溃。像平板电脑和可折叠设备一样,Chrome 操作系统现在也有了兼容模式,针对小屏移动设备设计的应用可在手机尺寸或平板尺寸的窗口中显示。

用户可轻松更改窗口的显示模式或按需启用窗口自由调整模式,但界面会告知用户,应用在完整的大屏幕模式下运行可能出现与预期不符的情况。这有助于 Chrome 操作系统提供符合预期的效果和稳定性,同时用户依然享有按照自己喜欢的方式与应用进行交互的自由。

在理想情况下您的应用不应该出现在兼容模式下。接下来我们聊聊在 Chrome 操作系统以及 Android 平板电脑和可折叠设备中避免应用出现在兼容模式中所需要做到的重要的几件事:

△ 运行在开放形式模式充分利用屏幕空间

△ 运行在开放形式模式充分利用屏幕空间

  1. 为不同的设备类型提供合适的大屏幕布局。
  2. 测试应用,确保应用能够处理折叠事件、旋转,能够移入分屏,能够自由调整大小。类似 ViewModel 等 Jetpack 组件简化了维护状态,并为用户提供符合预期的效果。一定要在真实设备或模拟器中测试不同的布局可能性。
  3. 根据应用需求妥善处理触摸、键盘、鼠标、触控板输入以及触控笔、游戏控制器等更为专业的输入方式。

如需更深入了解,请移步至我们在 Android 开发者峰会 上推出的更多关于大屏幕主题的技术分享,了解如何使布局更加美观、契合度更高,同时可以正确处理输入。如果您的应用已经在 Chrome 操作系统上呈现非常完美的外观,或是想了解从哪里开始优化,请 告知我们。关于针对 Chrome 操作系统以及大屏幕进行优化的详细文档,请访问 chromeos.dev

折叠设备、平板电脑和 Chromebook 越来越受大家欢迎。应用优化当前能做之事尚有很多,我们将继续努力推出新功能进一步提升应用效果。

总结

相信大家对 12L 对于大屏幕和应用设计上的一些新特性有了一定的了解。欢迎通过使用模拟器下载 12L 开发者预览版 探索 12L 中的全新 API。

可以尝试使用 JetpackWindowManager 优化应用,根据精确的窗口尺寸调整显示区域,启用姿态探测等新功能。在新的版本中可以利用 Activity 内嵌 和测试 API 进而简化大屏幕布局维护。

别忘了加入美观的大屏幕布局,并添加键盘、鼠标和其他输入支持。希望大家能够顺利完成对于大屏幕设备的应用改造来拥抱新的终端交互模式。

欢迎您 点击这里 向我们提交反馈,或分享您喜欢的内容、发现的问题。您的反馈对我们非常重要,感谢您的支持!

版权声明

禁止一切形式的转载-禁止商用-禁止衍生 申请授权

脉脉不得语
脉脉不得语
Zhengzhou Website
Android Developer | https://androiddevtools.cn and https://androidweekly.io Funder | GDG Zhengzhou Funder & Ex Organizer | http://Toast.show(∞) Podcast Host

你已经成功订阅到 Android 开发技术周报
太棒了!接下来,完成检验以获得全部访问权限 Android 开发技术周报
欢迎回来!你已经成功登录了。
Unable to sign you in. Please try again.
成功!您的帐户已完全激活,您现在可以访问所有内容。
Error! Stripe checkout failed.
Success! Your billing info is updated.
Error! Billing info update failed.
🍗