Android 使用Google Core动态功能交付(Feature Delivery)

Android接入应用内评分 应用内评论仅适用于以下设备: 运行Android 5.0(API级别21)或更高版本且已安装Google Play商店的Android设备(电话和平板电脑)。 装有Google Play商店的Chrome操作系统设备。 code示例 ReviewInfo reviewInfo; ReviewManager manager = ReviewManagerFactory.create(this); /*如果仅仅测试API 使用FakeReviewManager,此方法不模拟UI Review... 阅读详情

介绍

动态功能交付(Feature Delivery),是谷歌Google Play Core 库为谷歌商店发布的应用所提供的功能之一。

使用Play Core 库还可以提供以下这些功能:

  • 下载其他语言资源
  • 管理功能模块分发
  • 管理资源包分发
  • 触发应用内更新
  • 请求应用内评价

本文的重点是说明功能模块分发与资源包分发的使用。

Android App Bundle

Android App Bundle 是一种发布格式(.aab),这种格式和传统的apk类似,都会包含应用的所有经过编译的代码和资源。

不同之处在于将这种格式不能直接安装,而开发者需要将包上传至Google Play之后,Google Play会使用这个 App Bundle 包针对每种设备配置生成并提供经过优化的 APK,即 APK 的生成及签名交由了 Google Play 来完成。

如果要使用动态功能交付或资产交付,则必须要使用App Bundle方式打包。

如上图所示,传统的apk打包是将这些组成部分打包成一个压缩包,即apk包。而app bundle打包的aab文件也是包含以上所有内容,但是在将这个aab格式的包上传至Google Play后,用户进入商店选择下载应用时,下载的包将不是包含所有内容的包,而是只包含该用户手机所对应的相应类型资源的包。

如该用户的手机是使用英语、xhdpi、arm-v7架构cpu的设备,那么该用户下载到的包将只包含(如果你启用了这些类型的拆分)这些类型对应的语言、资源图、lib库文件。显而易见,这种方式将有助于缩小用户下载的包大小与减小应用所占用的空间。

而将现有的项目修改为app bundle打包的方法也很简单:

  1. 在项目gradle中引入google core库

    // In your app’s build.gradle file:
    ...
    dependencies {
        // This dependency is downloaded from the Google’s Maven repository.
        // So, make sure you also include that repository in your project's build.gradle file.
        implementation 'com.google.android.play:core:1.9.1'
    
        // For Kotlin users also import the Kotlin extensions library for Play Core:
        implementation 'com.google.android.play:core-ktx:1.8.1'
        ...
    }
    
  2. 在项目的app模块的build.gradle文件中添加以下内容:

android { // 在gradle的android结点下
    
    bundle {
        density {
            // Different APKs are generated for devices with different screen densities; true by default.
            enableSplit true
        }
        abi {
            // Different APKs are generated for devices with different CPU architectures; true by default.
            enableSplit true
        }
        language {
            // This is disabled so that the App Bundle does NOT split the APK for each language.
            // We're gonna use the same APK for all languages.
            enableSplit true
        }
    }
}
  1. 在打包时选择app bundle打包即可

这样打出来的包就是aab格式的包,发版时将这个aab文件传到谷歌后台即可。如果需要测试这个aab包的功能,则需要使用谷歌的bundletool工具来安装aab包到测试机上。

资产交付(Asset Delivery)

通常,对于用户不会立刻使用到的一些比较占用空间的assets资源,如大量图片资源、机器学习模型参数包、较大的视频资源等,可以使用动态资产交付。

具体的使用方式为,将这些资源单独拆分在一个Module的assets文件夹下,并将该Module设置为动态分发的模块。

动态资产交付主要有三种交付模式,分别为:

  • install-time:安装时分发,应用安装时就会下载,安装后可立即使用,资产包的大小会计入应用详情页的下载大小
  • fast-follow:快速跟进式分发,应用安装后会立即开始下载,安装后不一定保证可以使用,资产包大小暂时还不会计入详情页大小
  • on-demand:按需分发,资产包不会主动下载,需要代码在特定时机向用户征求开始下载,确保下载后才可使用,资产包大小不会计入详情页大小

这三种交付模式可以在资源Module的AndroidManifest.xml中设置。

代码中,对于动态分发的资源的访问,install-time与另外两种模式不同,对于install-time的模块,与常规资源一样使用AssertManager访问,官方代码示例为:

import android.content.res.AssetManager;
...
Context context = createPackageContext("com.example.app", 0);
AssetManager assetManager = context.getAssets();
InputStream is = assetManager.open("asset-name");

而对于另外两种模式,要访问动态分发模块的资源,则要复杂许多。

首先需要AssetPackManager#getPackLocation()方法获取 Asset Pack 的根文件夹。如果返回值存在,则说明动态模块可用,如果为null,则需要代码申请下载并安装该模块才可用。流程如下图,由于不是本文重点,故详细代码不列出来了。具体可以查看官方文档。

动态功能交付(Feature Delivery)

介绍

动态功能交付与资产交付类似,同样是需要单独拆分出一个模块,而且这个模块与常规的功能模块存在很大的不同。

我们通常添加一个模块,是希望这个模块中的代码能被多个项目复用,所以app模块与这个feature模块的引用关系为:app引用feature模块。

这种引用关系决定了app模块中可以随意使用feature模块中的代码和资源,而feature模块无法访问app中的资源和代码。

在动态功能交付中,这种引用关系需要反过来,feature模块引用app模块。所以feature中可以随意访问app中的代码和资源,而反过来则不行。

接下来,我们演示一下将一部分代码和资源从原有的项目中拆分出来。

在我负责的项目中,由于opencv的so文件占用的空间太大,产品不满意,所以决定将openCV对应的so文件和相应的activity页面与功能代码拆分出来配置成动态功能交付。

使用方式

首先,先新建一个Module,可以直接在AS中选择创建动态功能交付的Module,然后根据提示填好Module的Name和Title。

创建完成之后,确认以下配置:

app的gradle文件中,以动态模块的形式引入了刚刚创建的模块

android { // android结点下
    
    dynamicFeatures = [':opencvfeature']
}

创建模块的gradle文件中,引入了app模块

dependencies {
    implementation project(":app")
}

新创建的模块AndroidManifest.xml文件中,已经添加了以下内容:

    <dist:module dist:title="@string/module_name">
        <dist:delivery>
            <dist:on-demand />
        </dist:delivery>
        <dist:fusing dist:include="true" />
    </dist:module>

确认以上内容后,一个动态功能交付的模块就创建完成了。接下来要做的工作就是将原app模块中需要拆分的代码迁移到新创建的这个模块中,并消除app模块对这部分代码的引用(即能成功编译)。这部分工作和每个人的项目相关,有些甚至需要重构功能代码,所以就不展开讲了。

在这个过程中可能会发现一个问题,那就是app模块无法引用动态模块中的代码和资源后,那动态模块我要如何使用呢?无法引用其中的类,也就无法调用其中的功能方法,那动态分发的意义在哪里?

这个问题的答案也很简答:使用反射。

对于调用动态模块中的代码,使用反射的方式去调用对应类中的方法。对于跳转动态模块中的activity,使用Intent指定类名和包名即可,示例如下。

Intent intent = new Intent();
intent.setClassName(getPackageName(), "com.xxx.xxx.XXXActivity");
startActivityForResult(intent, requestCode);

修改代码完成后,工程目录大致如下,其中opencvfeature就是我拆分出的动态功能模块。

完成了以上工作,还有一个重要的工作没有完成,即使用该模块的功能前,判断模块是否安装以及申请下载安装该模块,毕竟我们的功能模块设置的是on-demand(按需交付)模式。

private SplitInstallManager splitInstallManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
	// ...
    splitInstallManager = SplitInstallManagerFactory.create(this); // 创建manager
}

@Override
public void onResume() {
	// ...
    splitInstallManager.registerListener(splitInstallStateUpdatedListener);
}

 @Override
public void onPause() {
    // ...
    splitInstallManager.unregisterListener(splitInstallStateUpdatedListener);
}

// 使用动态模块功能
public void tryUseDynamicFeature() {
    String moduleName = FeatureManager.getInstance().getModuleName();
    if (splitInstallManager.getInstalledModules().contains(moduleName)) {
        // 已下载对应的模块
        // TODO 使用反射代码
        
    } else { // 没有下载模块,需要申请下载
        SplitInstallRequest request = SplitInstallRequest.newBuilder().addModule(moduleName).build();
        splitInstallManager.startInstall(request);

        boolean isGoogleCanUse = PhoneUtil.isGooglePlayServiceAvailable(this);
        if (isGoogleCanUse) {
            T.show("Starting install for " + moduleName);
        } else {
            T.show("The Google service appears to be unavailable and the installation cannot begin");
        }
    }
}

// 动态模块的状态监听
private final SplitInstallStateUpdatedListener splitInstallStateUpdatedListener = state -> {
        switch (state.status()) {
            case SplitInstallSessionStatus.DOWNLOADING: {
                // 正在下载
            }
            break;
            case SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION: {
                // 需要用户确认
            }
            break;
            case SplitInstallSessionStatus.INSTALLED: {
                // 安装模块成功
            }
            break;
            case SplitInstallSessionStatus.INSTALLING: {
                // 正在安装
            }
            break;
            case SplitInstallSessionStatus.FAILED: {
                // 下载模块失败
            }
            break;
            default:
                break;
        }
    };
动态交付的优势
  • 减少必要apk的体积,使得在流量分发中更具优势
  • 使用谷歌官方服务器分发,稳定性更有保障,不需要消耗宝贵的服务器资源
  • 下载过程由google自身处理,支持断点续传等
注意事项
  • 动态功能交付和资产交付不同,只有两种模式,install-time和on-demand,没有提供fast-follow
  • 测试动态功能交付需要使用Google Play提供的测试服功能,将包当作测试包传上商店,将测试的账号加入测试账号列表,即可测试
Android 打包AAB+PAD(java篇),音视频开发进阶指南下载 如果你使用的是纹理压缩格式定位,那么这些下载限制会分别应用于每个独一无二的纹理格式。 针对Java 代码构建 你可以按照以下步骤将 Play Asset Delivery 内置到项目的 Android App Bundle 中。你无需使用 Android Studio 即可执行这些步骤。 1、将 Play Core 库导入项目。 // In your app’s build.gradle file: … dependencies { //&n 阅读详情

相关推荐

Play Asset Delivery实践篇 (踩坑-2021.11.27修改)

闲聊 最近一段时间,开始负责一个游戏项目安卓SDK对接工作,又是熟悉的味道还是那个配方。从游戏研发边缘成员折腾回安卓SDK对接工作中(再次入坑)。 马上快8月了Google 上架游戏政策又发生变化,手中对接游戏主要发往海外。所以Google的要求我们还是要满足的。想想发往国内的游戏渠道,真是幸福。 废话说完,进入今天正题。针对Google 8月份新规 游戏这块需要作出调整以应对新规,正好做个记录,以踩坑者的角度去记录一下过程。 上架Google时间轴 开发者应该着重关注8月份起新政策。新应用8月份上架Go

北京朝阳区精神病院院长 1万+

Google市场,APP版本更新实现方式

一、直接跳转google play应用详情 直接跳转到google play应用详情内由用户手动触发版本更新。 实现方式包括两种:跳转到google play app应用详情内和跳转到google play网页版应用详情内。 一般实现原则是用户如果安装了google play app跳转到app,未安装跳转到网页。 优点:代码实现简单不需要依赖额外代码,由google play提供下载安装,方便测试。 缺点:需要界面调整动作。 参考链接:https://developer.andro..

mingzaizai_123的专栏 7357

Android AAB打包全流程解析:从配置、调试到Play商店上架实战

在Android应用开发中,应用打包与分发是连接开发与用户的关键环节。传统的APK打包方式虽然简单直接,但存在安装包体积大、资源适配不灵活等局限。其原理是将所有代码和资源打包进单一文件,导致用户无论设备配置如何,都需要下载完整内容。随着应用功能日益复杂,这种模式在用户体验和开发效率上的瓶颈愈发明显。Android App Bundle(AAB)作为一种新的发布格式,通过模块化设计和动态交付机制,从根本上改变了这一流程。AAB将应用拆分为基础模块和按需模块(如特定语言、屏幕密度或CPU架构的资源),当用户从G

weixin_34081595的博客 538

com.google.android.play:core 升级

com.google.android.play:core 是服务Google play的核心库,包含了Google play评价、应用内更新等功能,现被拆分。拆分文档:https://developer.android.google.cn/guide/playcore?

那个男人,你快乐吗? 1031

Android App Bundle (AAB) vs APK:3大核心差异与迁移实战指南

本文深入比较了Android App Bundle (AAB)与传统APK的三大核心差异,包括动态分发机制、体积优化技术和签名安全机制,并提供了从APK迁移到AAB的完整实战指南。通过模块化设计和按需交付,AAB能显著减少应用体积20-35%,提升用户体验和开发效率。

ainixi7099的博客 408

Android App Bundle (AAB) 打包、调试与上架全流程实战指南

在移动应用开发领域,应用分发格式的演进直接影响着用户体验与开发者效率。从传统的APK到现代的Android App Bundle (AAB),其核心原理在于通过模块化与按需交付技术,实现应用体积的显著优化。这项技术的核心价值在于,它能根据用户设备的屏幕密度、CPU架构和语言设置,动态生成并分发最小的必要APK分片,从而减少下载数据量、提升安装速度并节省设备存储空间。在工程实践中,这直接关系到应用的安装转化率与用户留存。本文聚焦于AAB的实战应用,详细解析了其打包配置、本地调试方法以及Google Play上

weixin_34417200的博客 342

Android App Bundle技术解析与优化实践

Android应用打包技术经历了从APK到AAB的演进,其核心原理是通过模块化架构实现资源按需分发。作为Google Play官方推荐的发布格式,AAB采用差异化构建策略,根据设备配置动态生成最优APK组合,显著提升交付效率。这项技术在工程实践中展现出两大核心价值:安装包体积平均可缩减30%以上,同时简化多APK变体维护成本。典型应用场景包括游戏资源动态加载、即时应用体验优化等热门领域。特别是在Play Asset Delivery和动态功能模块的配合下,开发者能够实现更精细化的资源管理策略。热词分析显示,

weixin_30263073的博客 594

Unity游戏AAB打包实战:告别150M限制,实现资产按需分发

在移动应用分发领域,APK(Android Package)是传统的应用打包格式,但其单一的体积限制(如Google Play的150MB)常导致开发者需使用繁琐的扩展文件(OBB)。为解决此痛点,Google推出了Android App Bundle(AAB)这一官方格式,其核心原理在于“动态分发”。AAB并非一个直接安装的包,而是一个包含所有代码和资源的“描述文件”。上传至Google Play后,商店会根据用户设备的特定配置(如CPU架构、语言、屏幕密度),利用bundletool工具动态生成并下发最

weixin_30279315的博客 850

2023最新Google Play发布指南:避开APK/AAB大小限制的5个实用技巧

本文深入解析了Google Play最新的应用分发机制,特别是针对APK和AAB的大小限制。文章提供了5个核心实战技巧,包括理解分发演进、基础模块瘦身、利用Play Asset Delivery (PAD)管理大型资源、通过Play Feature Delivery (PFD)实现模块化,以及关键的发布流程与版本管理要点,帮助开发者有效规避限制,优化应用架构与用户体验。

happy2的博客 1164

Android Studio生成aar包全流程与优化实践

在Android模块化开发中,aar(Android Archive)作为包含资源文件和Manifest的二进制分发格式,是组件化架构的核心载体。与标准jar包相比,aar专为Android平台设计,能够封装res资源、assets目录和JNI库等元素。通过Gradle构建系统,开发者可以配置consumerProguardFiles实现代码混淆的自动传递,使用resourcePrefix避免资源冲突。在电商App等大型项目中,合理使用aar模块能使团队协作效率提升40%以上。本文详解从环境配置、工程结构设

weixin_30696427的博客 391

Android APK 文件结构深度解析:7大核心目录与文件作用详解

本文深入解析Android APK文件结构的7大核心目录与文件作用,包括assets、lib、META-INF等关键目录,以及AndroidManifest.xml、classes.dex等重要文件。通过详细分析APK构建流程和安全验证机制,帮助开发者优化应用性能并增强安全性,适用于Android开发、逆向工程和安全分析领域。

weixin_34221276的博客 351

如何从零开始使用app-bundle-samples:新手必备的Android模块化开发教程

Android App Bundle是现代Android应用开发的重要技术,而app-bundle-samples项目正是学习这一技术的绝佳资源。这个开源项目提供了多个实用示例,展示了Android App Bundle和动态功能模块的最佳实践。无论你是Android开发新手还是希望提升技能的老手,这个项目都能帮助你快速掌握模块化开发的核心概念。本文将为你提供完整的入门指南,带你从零开始使用app

gitblog_01171的博客 478

别再为TFLite模型下载发愁了!一份完整的离线集成指南(含mnist、yoga_classifier等模型地址整理)

本文提供了一份完整的TensorFlow Lite(TFLite)模型离线集成指南,涵盖从官方模型下载到团队协作的最佳实践。详细介绍了常见TFLite模型资源(如mnist、yoga_classifier等)的获取策略、项目内模型管理方案以及企业级离线集成方法,帮助开发者解决网络依赖问题,提升开发效率。

weixin_30352645的博客 358

为什么选择Android App Bundle?app-bundle-samples揭示模块化开发的7大优势

Android App Bundle是Google推出的全新应用发布格式,它能够大幅优化应用体积、提升用户体验并简化开发流程。通过app-bundle-samples项目提供的多个示例,我们可以清晰地看到模块化开发为Android应用带来的显著优势。本文将深入解析Android App Bundle的核心价值,帮助开发者理解为什么它已成为现代Android应用开发的首选方案。 ## 1. 显著减

gitblog_00036的博客 871

HFSS实战(三)——过孔via TDR仿真

在上一讲中,主要是通过观察S参数确定via的优化是否达到目标。但S参数只能看到一个整体的结果,并不知道via真实的阻抗是多少?想要单独确定via的阻抗,最好还是通过TDR的仿真。

luohuo9844的博客 1万+

详解Σ-Δ型ADC拓扑结构的基本原理

现在,总环路滤波器的H(f)具有更大的滚降,Mod 2型的噪声传递函数具有40 dB/十倍频程的上升速率。同样,当正弦波输入为负满量程时,+1和–1之间的转换会减少,输出以–1为主。噪声传递函数是一个高通滤波器函数,提供噪声整形,在DC附近的较低频率,对量化噪声有很强的抑制。H(f)是环路滤波器的函数,定义噪声和信号的传递函数。Σ-Δ型ADC的噪底由热噪声决定,而不受量化噪声的限制。量化噪声为量化器的输入与输出之差。图5. Mod 1 Σ-Δ环路的线性模型(b),包括方程、滤波器、信号和噪声传递函数图。

qq_43416206的博客 1810

5分钟上手Android即时应用:基于app-bundle-samples的快速启动指南 [特殊字符]

想要在5分钟内掌握Android即时应用的开发技巧吗?这篇快速指南将带你深入了解如何利用Google官方的app-bundle-samples项目快速构建即时应用。Android即时应用是一种无需安装即可使用的轻量级应用体验,让用户能够快速体验应用的核心功能。 ## 什么是Android即时应用? 🤔 Android即时应用(Instant Apps)是Android生态系统中一项革命性的技

gitblog_00709的博客 420

VMware + ubuntu20.04 + qemu安装

遇到报错可参考:(从ubuntu裸系统开始安装)

NosONE 3230

React Native APK签名打包全流程与优化指南

Android应用签名是确保应用完整性和来源可信的核心安全机制,采用RSA算法对APK进行数字签名。在React Native跨平台开发中,通过keytool生成密钥库(Keystore)并配置Gradle实现自动化签名,是发布流程的关键环节。合理的签名策略不仅能满足Google Play上架要求,还能有效防止应用被篡改。针对性能优化,可通过ABI分包、资源压缩和Hermes引擎显著提升运行效率。结合Fastlane等CI/CD工具,开发者可以构建从代码提交到应用商店发布的完整自动化流水线,特别适合需要频繁

weixin_30386713的博客 363

R语言maftools包实战:5分钟搞定TCGA癌症突变数据可视化(附完整代码)

本文详细介绍了如何使用R语言的maftools包快速解析和可视化TCGA癌症突变数据。通过实战演示,从环境搭建、数据导入到核心可视化(如瀑布图、棒棒糖图)和深度统计分析(如生存分析、突变特征),帮助生物信息学研究者高效完成癌症基因组学分析,大幅提升从原始MAF数据到发表级图表的效率。

weixin_29054399的博客 189

在Qt中使用EtherCAT-SOEM的初始化中,状态机卡在PreOp->Save-Op过程中,出现State=0x12, Error=0x001e错误的解决办法

1.在调试EtherCAT软件过程中,一直出现配置从站进不了Save_op状态,通过下函数检查从站状态: //使用的从站编号为1 只有1个从站 ec_slave[1].state = EC_STATE_SAFE_OP; ec_writestate(1); //设置到安全模式 ec_statecheck(1, EC_STATE_SAFE_OP, EC_TIMEOUTSTATE * 4); printf("Slave %d State=0x%2.2x StatusCode=0x%4

zeal_for_rov的博客 6828

Android应用架构演进:从MVC到MVVM与Jetpack实践

移动应用架构设计是Android开发的核心课题。从早期的MVC模式到如今的MVVM架构,Android系统通过数据绑定、ViewModel等Jetpack组件实现了UI与业务的解耦。现代架构强调分层设计,包括UI层、领域层和数据层,配合LiveData实现响应式编程,同时依赖注入工具如Hilt简化了组件管理。在工程实践中,Jetpack Compose进一步推动了声明式UI与状态管理的革新,而模块化设计和KMM技术则为跨平台开发提供了新思路。对于Android开发者而言,掌握MVP到MVVM的演进历程,理解

weixin_33674976的博客 373

后仿真中的关于延时问题(物理特性角度)

大家都知道,后仿真讲究仿真时序。那么,在网表阶段,接触到后仿延时问题。今天总结一下。

那么菜的博客 1772

Android开源项目精选:提升开发效率的实用指南

Android开源项目(AOSP)是移动开发领域的核心资源,通过复用成熟方案可显著提升开发效率。现代Android开发中,架构组件如Jetpack通过生命周期感知和类型安全设计解决了内存管理和数据持久化等基础问题,而Retrofit+OkHttp组合则为网络通信提供了标准化解决方案。在UI层面,Jetpack Compose采用声明式编程范式,大幅简化界面开发流程。性能优化工具如LeakCanary能有效检测内存泄漏,App Startup则优化了启动时序。这些经过生产验证的开源项目覆盖了从基础框架到前沿技

weixin_30565327的博客 277

杰理SDK UART 使用教程

本文介绍了JL701n芯片的UART串口通信使用教程,重点讲解了UART2的初始化配置、数据收发和中断处理功能。教程详细说明了代码结构、核心功能函数、配置参数和使用步骤,包括UART初始化、数据发送和接收中断处理等关键操作。同时提供了完整的API接口说明和注意事项,强调了中断处理限制、缓冲区管理、引脚配置等重要细节。最后给出了基本使用流程和高级任务处理示例,并针对常见问题提供了故障排除建议。本教程适用于需要在JL701n芯片上实现可靠串口通信的开发者。

qq_42014563的博客 1819

AI原生SaaS应用的自动化运维体系构建

随着ChatGPT掀起的AI原生应用浪潮,越来越多SaaS(软件即服务)产品开始以"AI优先"的方式设计——从用户交互到核心功能,都深度依赖机器学习模型(如推荐算法、智能客服)、实时数据流(如用户行为分析)和弹性算力(如大模型推理)。这类应用的运维需求与传统SaaS完全不同:传统运维像"修水管",哪里漏了补哪里;AI原生运维则像"照顾会成长的宠物",需要实时感知模型状态、数据变化和流量波动,主动调整资源。

AI天才研究院 1080
上一篇: 算法题系列(一)
Fu_Long
博客等级 码龄10年 4粉丝 4原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值