编辑后的文案:构建具备动态下载模块功能的App Bundle(编辑后的文案怎么写)(编辑 文案)

访客 114 0

文章目录

  • 摘要
  • 创建module
  • 依赖
  • Application
  • Dynamic Feature Module
  • App主模块
  • 本地构建调试
  • 拆分注意事项
  • 问题
  • 结束语

摘要

Android App Bundle 是一种发布格式,其中包含您应用的所有经过编译的代码和资源,它会将 APK 生成及签名交由 Google Play 来完成。

Google Play会根据每种设备配置使用您的App Bundle生成并提供经过优化的APK,这样只会下载特定设备所需的代码和资源来运行您的应用。这意味着您无需再构建、签署和管理多个APK以优化对不同设备的支持,同时用户也可以获得更小且更优化的下载文件包。

对于大多数应用项目而言,构建App Bundle以支持提供经过优化的APK并不费力。举个例子,如果您已经按照既定惯例组织管理应用的代码和资源,只需使用Android Studio或命令行来构建已签名的Android App Bundle,并将其上传到Google Play。这样一来,您就能够自动享受到经过优化的APK所带来的种种好处了。

当您使用App Bundle格式发布应用时,您还可以选择使用Play Feature Delivery。它允许您向应用项目中添加功能模块,这些模块包含仅在满足特定条件时提供给应用的功能和资源,或者在运行时通过Play核心库下载供后续使用。

通过使用App Bundle来发布应用,游戏开发者可以利用Play Asset Delivery来分发大量的游戏资产。Play Asset Delivery是Google Play为此而提供的解决方案,它为开发者提供了灵活的分发方式和卓越的性能表现。

编辑后的文案:构建具备动态下载模块功能的App Bundle(编辑后的文案怎么写)(编辑 文案)-第1张图片-谷歌商店上架

创建module

编辑后的文案:构建具备动态下载模块功能的App Bundle(编辑后的文案怎么写)(编辑 文案)-第2张图片-谷歌商店上架
编辑后的文案:构建具备动态下载模块功能的App Bundle(编辑后的文案怎么写)(编辑 文案)-第3张图片-谷歌商店上架
编辑后的文案:构建具备动态下载模块功能的App Bundle(编辑后的文案怎么写)(编辑 文案)-第4张图片-谷歌商店上架

依赖

主模块App需要进行以下依赖:

请改写下面的这段话:

```java
implementation 'com.google.android.play:core-ktx:1.8.1'
implementation 'com.google.android.play:core:1.10.0'
```

Application

主模块App的Application需要继承SplitCompatApplication

改写为: ```java // 添加以下依赖库 implementation 'com.google.android.play:core-ktx:1.8.1' implementation 'com.google.android.play:core:1.10.0' // 在主模块App的Application中继承SplitCompatApplication类 public class MyApplication extends SplitCompatApplication { // 其他代码... } ``` 希望对你有所帮助!
```kotlin


    
    

    
        
        

    

```

```java
class App : SplitCompatApplication() {
    
}
```
 
plugins {
    id 'com.android.dynamic-feature' ...
}

dependencies {
    // code here
} 

    

        
            
 属性说明<manifest ...这是您的典型 <manifest> 块。xmlns:dist="http://schemas.android.com/apk/distribution"指定一个新的 dist: XML 命名空间,如下所述。split="split_name"当 Android Studio 构建 app bundle 时,会包含该属性。因此,您不应自行添加或修改此属性
定义模块的名称,当应用使用 Google Play 核心库发出按需模块请求时会指定该名称。
Gradle 如何确定该属性的值
默认情况下,当您使用 Android Studio 创建功能模块时,IDE 会使用您指定的模块名称,在 Gradle 设置文件中将该模块标识为 Gradle 子项目。
当您构建 app bundle 时,Gradle 会使用子项目路径的最后一个元素将此清单属性注入模块的清单。例如,如果您在 MyAppProject/features/ 目录中创建了一个新功能模块,并指定了“dynamic_feature1”作为其模块名称,IDE 会在 settings.gradle 文件中添加 ':features:dynamic_feature1' 作为子项目。构建 app bundle 时,Gradle 会将 <manifest split="dynamic_feature1"> 注入模块的清单。android:isFeatureSplit="true | false">当 Android Studio 构建 app bundle 时,会包含该属性。因此,您不应手动添加或修改此属性
指定此模块为功能模块。基本模块和配置 APK 中的清单要么省略此属性,要么将其设置为 false<dist:module这一新的 XML 元素定义了一些属性,这些属性可确定如何打包模块并作为 APK 分发。dist:instant="true | false"指定是否应通过 Google Play 免安装体验为模块启用免安装体验。
如果应用包含一个或多个启用免安装体验的功能模块,您也必须为基本模块启用免安装体验。如果您使用的是 Android Studio 3.5 或更高版本,当您创建支持免安装体验的功能模块时,IDE 会为您完成此操作。
在设置 <dist:on-demand/> 时,不能将此 XML 元素设置为 true。不过,您仍可使用 Play Core 库请求以免安装体验的形式按需下载支持免安装体验的功能模块。当用户下载并安装您的应用时,设备会默认下载并安装应用的支持免安装体验的功能模块以及基本 APK。dist:为模块指定一个面向用户的名称。例如,当设备请求确认下载时,便可能会显示该名称。
您需要将此名称的字符串资源包含在基本模块的 module_root/src/source_set/res/values/strings.xml 文件中。<dist:fusing dist:include="true | false" /> </dist:module>指定是否在面向搭载 Android 4.4(API 级别 20)及更低版本的设备的 multi-APK 中包含此模块。
此外,当您使用 bundletool 从 app bundle 生成 APK 时,只有将此属性设置为 true 的功能模块才会包含在通用 APK 中。通用 APK 是一个单体式 APK,其中包含了应用所支持的所有设备配置的代码和资源。<dist:delivery>封装自定义模块分发的选项,如下所示。请注意,每个功能模块必须只配置这些自定义分发选项的一种类型。<dist:install-time>指定模块应在安装时可用。对于未指定自定义分发选项的其他类型的功能模块,这是默认行为。
如需详细了解安装时下载,请参阅配置安装时分发。
此节点还可以指定条件,用于限定要下载模块的设备所需满足的某些要求,例如设备功能,用户所在国家/地区或最低 API 级别。如需了解详情,请参阅配置按条件分发。<dist:removable dist:value="true | false" />当未设置或设置为 false 时,bundletool 会在根据 bundle 生成拆分 APK 时将安装时模块整合到基本模块中。 由于整合会使拆分 APK 的数量减少,因此此设置可以提升应用的性能。
removable 设置为 true 时:安装时模块将不会整合到基本模块中。如果您想要在将来卸载这些模块,请将其设置为 true。 不过,配置过多可移除的模块可能会导致应用的安装时间增加。
默认为 false。只有当您想要针对某个功能模块停用融合功能时,才需要在清单中设置此值。
注意:只有在使用 Android Gradle 插件 4.2 或从命令行使用 bundletool v1.0 时,才能使用此功能。</dist:install-time><dist:on-demand/>指定应以按需下载的形式分发模块。也就是说,模块在安装时不会下载,但应用可以稍后请求下载。
如需详细了解按需下载,请参阅配置按需分发。</dist:delivery><application [android:hasCode](https://developer.android.google.cn/guide/topics/manifest/application-element#code)="true | false"> ... </application>如果功能模块没有生成 DEX 文件(也就是说,它不包含之后编译成 DEX 文件格式的代码),您必须执行以下操作(否则,您可能会遇到运行时错误):
1. 在功能模块的清单中将 android:hasCode 设置为 "false"
2. 将以下内容添加到基本模块的清单中:
<application<br> android:hasCode="true"<br> tools:replace="android:hasCode"><br> ...<br></application>

App主模块

  • 检查需要调用的模块是否安装
  • 如果没有安装则下载,这个过程是googlePlayCore库处理的
  • 如果已安装通过全类名进行调用访问
class MainActivity : AppCompatActivity() {    val muduleName = "login_feature"    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_main)        val manager = SplitInstallManagerFactory.create(this)        //安装模块监听        manager.registerListener {            val status=it.status()            Log.d("TAG", it.toString())        }        loginModule.setOnClickListener {            //模块已安装            if (manager.installedModules.contains(muduleName)) {                val intent = Intent()                val componentName =                    ComponentName(packageName, "cn.xxstudy.login_feature.LoginActivity")                intent.component = componentName                startActivity(intent)            } else {                //安装模块:                GlobalScope.launch {                    try {                        manager.requestInstall(listOf(muduleName))                    } catch (e: Exception) {                        MainScope().launch {                            Toast.makeText(this@MainActivity, "该模块还未安装成功", Toast.LENGTH_SHORT).show()                        }                    }                }            }        }    }    override fun attachBaseContext(newBase: Context?) {        super.attachBaseContext(newBase)        //必须添加        SplitCompat.install(this)    }}

manager.registerListener安装监听status说明:

SplitInstallSessionStatus.CANCELED -> 模块下载已被取消SplitInstallSessionStatus.CANCELING -> 正在取消下载SplitInstallSessionStatus.DOWNLOADING -> Installing(        state.bytesDownloaded.toDouble() / state.totalBytesToDownload)下载进度SplitInstallSessionStatus.DOWNLOADED -> 下载完成但未安装SplitInstallSessionStatus.FAILED ->下载或安装失败SplitInstallSessionStatus.INSTALLED -> 安装完成SplitInstallSessionStatus.INSTALLING -> 安装中SplitInstallSessionStatus.PENDING -> 将要进行下载SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION -> 需要用户确认,大于10MSplitInstallSessionStatus.UNKNOWN -> 未知错误

本地构建调试

  1. 调试
    编辑后的文案:构建具备动态下载模块功能的App Bundle(编辑后的文案怎么写)(编辑 文案)-第5张图片-谷歌商店上架
    接下来运行后login_fuature模块就不会被安装了,当然也是无法使用该模块的
    编辑后的文案:构建具备动态下载模块功能的App Bundle(编辑后的文案怎么写)(编辑 文案)-第6张图片-谷歌商店上架
  2. 生成.aab
  • Build→Build Bundle(s)/ APK→Build Bundle(s)
  • Build→Generate Sigend Bundle Apk →Android App Bundle
  1. 通过BundleTool生成.apks
java -jar F:\Temp\bundletool.jar  build-apks --local-testing --bundle=app/build/outputs/bundle/debug/app-debug.aab --output=app.apks
  1. 安装
java -jar F:\Temp\bundletool.jar install-apks --apks=app.apks

编译过程:

E:\Android\Simple\Temp\PlayCoreDemo>java -jar F:\Temp\bundletool.jar  build-apks --local-testing --bundle=app/build/outputs/bundle/debug/app-debug.aab --output=app.apksINFO: The APKs will be signed with the debug keystore found at 'C:\Users\DELL\.android\debug.keystore'.E:\Android\Simple\Temp\PlayCoreDemo>java -jar F:\Temp\bundletool.jar install-apks --apks=app.apksThe APKs have been extracted in the directory: C:\Users\DELL\AppData\Local\Temp\1369014306226025145The APKs have been extracted in the directory: C:\Users\DELL\AppData\Local\Temp\1369014306226025145ADB << rm -rf '/sdcard/Android/data/cn.xxstudy.demo/files/local_testing'ADB >> OKADB << mkdir -p '/sdcard/Android/data/cn.xxstudy.demo/files/local_testing' && rmdir '/sdcard/Android/data/cn.xxstudy.demo/files/local_testing' && mkdir -p '/sdcard/Android/data/cn.xxstudy.demo/files/local_testing'ADB >> OKPushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-xxhdpi.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-master.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-ca.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-da.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-fa.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-ja.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-ka.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-pa.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-ta.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-nb.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-be.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-de.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-ne.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-te.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-af.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-bg.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-th.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-fi.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-hi.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-si.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-vi.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-kk.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-mk.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-sk.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-uk.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-el.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-gl.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-ml.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-nl.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-pl.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-sl.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-tl.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-am.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-km.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-bn.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-in.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-kn.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-mn.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-ko.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-lo.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-ro.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-sq.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-ar.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-fr.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-hr.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-mr.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-or.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-sr.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-tr.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-ur.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-as.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-bs.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-cs.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-es.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-is.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-ms.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-et.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-it.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-lt.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-pt.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-eu.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-gu.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-hu.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-ru.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-zu.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-lv.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-sv.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-iw.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-sw.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-hy.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-ky.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-my.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-az.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-uz.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-en.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/base-zh.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/login_feature-xxhdpi.apk"Pushed "/sdcard/Android/data/cn.xxstudy.demo/files/local_testing/login_feature-master.apk"

这个时候就将login_feature模块导入到设备中去了,执行manager.requestInstall(listOf(muduleName))后就会进行安装了(一般是通过googlePlay下载,我们这里是使用BundleTool本地测试)
编辑后的文案:构建具备动态下载模块功能的App Bundle(编辑后的文案怎么写)(编辑 文案)-第7张图片-谷歌商店上架

拆分注意事项

  1. dynamic-feature-module 引用 base module 资源时,不能直接使用 R.drawable,而是需要使用 [base module package name].R.drawable 的方式。

  2. 请勿以数字开头命名动态功能模块(dynamic-feature-module)项目。

  3. 需要注释掉build.gradle中的splite {abi{}},否则会出现java.lo.lOException: Cannot find PROCESSED_ RES output for Main{type=MAIN, fullName=flavor1Debug, filters=I, versionCode=-1, versionName=null}异常。

  4. base module无法访问dynamic-feature-module中的id。在dynamic-feature-moduleR.java文件中,资源索引id 的值为 0x7e ,而在 base module 的 R.java i d c ode c ode>

标签: 谷歌商店上架 模块 文案

发表评论 (已有0条评论)

还木有评论哦,快来抢沙发吧~