app bundle_app bundleid 查看 - CSDN
精华内容
参与话题
  • Android App Bundle的学习整理

    万次阅读 2018-10-18 22:39:04
    对于手机用户来说,“存储空间不足” ...如何针对不同的用户给出最优的安装体验,正是 Android App Bundle 所要解决的问题 传统的APK Android Package Kit 包含了应用支持的所有设备的代码和资源,您在安装apk是...

    对于手机用户来说,“存储空间不足” 警告有时会显得非常烦人。时至今日,手机存储容量仍然是有限的。虽然存储容量多年来一直在增长,但是填充在我们手机里的东西:音乐、应用、游戏、照片等也同样在增长。如何针对不同的用户给出最优的安装体验,正是 Android App Bundle 所要解决的问题

    传统的APK

    • Android Package Kit
    • 包含了应用支持的所有设备的代码和资源,您在安装apk是可能装上了一些永远也用不到的资源。
    • 很明显,apk里的内容比您要求的还要多,占用的空间比实际需要的更多
    • Android app Bundle的出现可以让开发者用更小的apk交付同样卓越的应用。

    Android App Bundle 是什么?

    • 是一种的新的发布格式。
    • 准确的说,是一个带有.abb扩展名的zip文件。
    • 包含应用支持的所有设备的代码和资源。例如DEX文件,本地代码库,清单文件,资源文件等。
    • 一旦上传发布,Google Play就会处理APK的签名和生成,这个过程称为动态交付(Dynamic Delivery)
    • 动态交付的优点:根据用户的设备配置为用户生成优化的APK

    在这里插入图片描述

    • 分拆 APK (在 Lollipop 中引入) 是从给定的 Android App Bundle 生成的,其行为与单个 APK 无异
    • 一个典型的应用可以获得一个基础APK多个配置APK
    • 基本APK包含所有设备配置共有的文件,如清单文件。
    • 配置APK就是为用户生成的了,每个里面都包含了特定设备配置的相关资源:语言,CPU架构,或者屏幕密度。
    • 到用户设备里的就是基本APK(其他任何设备也会获得)以及包含用户设备相关资源的配置APK。

    详细解释

    • 我手上有一台小米A1,我设置了主要语言为英语。
    • 那么我下载到的apk就是基础APK以及支持英文,arm64 CPU架构和xhdpi屏幕分辨率的配置APK。
    • 更厉害的是:当你的设备配置(如语言)发生改变,Google Play会检测到它,并下载该语言的配置APK。

    动态功能 APK

    • 动态功能 APK包含用户首次安装应用时 不需要的应用功能和资源。
    • 开发者可以把这些功能添加到应用中,Google Play会按需提供这些动态功能模,而不是在安装时统一添加,从而进一步减少应用下载体积。
    • 简单理解就是:我们有必要将那些消耗空间且在安装时根本用不着的功能,以及那些很少用得着的功能,都打包进动态功能模块中,这将显著减少用户安装时的文件下载量。

    Android App Bundle != APK

    Android App Bundle 与 APK 有一些相似之处,但它们是截然不同的,且用于不同的目的。

    • APP Bundle(应用束)纯粹是为了上传设计的文件,用户无法直接安装和使用它。它是一个zip文件,Google Play 从中生成优化的APK并将其提供给设备进行安装。
    • 应用束包含用于帮助工具生成 APK 的元数据文件 (这些元数据文件最终不会出现在 APK 中),此外还拥有严格的验证标准。

    从 APK 切换到应用束是一个无缝过程。如果您使用 Android Studio 3.2 及更高版本,那么您只需点击几下即可生成已签名的应用束,将其上传到 Play Store,即可让用户开始享受更小尺寸 APK 所带来的便利。由于您的代码库没有重大变化,因此您无需担心会有什么问题发生。Android App Bundle 的早期采用者已经发现,动态交付显著减小了他们的应用体积。一些开发者甚至可以将他们的 APK 大小减半

    Android App Bundle 的好处都有哪些?

    • 体积小,用户安装时无需考虑是否需要腾出空间
    • Android App Bundle 是单一工件,因此无需构建、签名或管理多个 APK
    • 您可以为特定用例和受众添加动态功能,而无需增加安装时的应用体积

    构建 App Bundle

    • 在 Android Studio 中打开项目后,转到菜单栏并选择 Build > Build Bundle(s)/ APKs > Build Bundle(s)。等待生成应用束。您可以在生成应用束后的弹出窗口中点击选项来找到生成的 .aab 文件,并进行分析
    • 想要生成签名版本的话,请选择Build > Generate Signed Bundle/APK… > Android App Bundle > Select Base Module > Enter Signing Credentials & Check any other options (和您操作 APK 所做的事情一样)
    • 想要更好地控制从 Android App Bundle 进行拆分的方式的话,您可以从应用束的设置区块中进行精确设置:
    android {
        ...
        bundle {
            density {
                enableSplit = <true or false>
            }
            
            language {
                enableSplit = <true or false>
            }
            
            abi {
                enableSplit = <true or false>
            }
        }
    }
    

    小结

    • 正如我们所见,Android App Bundle 代表着 Android 应用交付的未来,提供单一的 APK 的做法已经过时。应用体积可以减小,而且还可以提供定制功能,为每个用户提供度身定制的体验
    • 更棒的是,开发者并不需要花费太大力气就可以尽享这些收益。一些开发者已经发现应用体积大幅减少。用户也可以获得极大的好处,因为他们的设备可以为音乐、电影、应用等其他内容提供更多的可用空间。开发者还可以通过使用 Android Vitals 进一步提高其应用在用户设备上的性能和稳定性。

    参考

    展开全文
  • app bundle

    2012-06-13 11:53:39
    [size=medium]=。= c++的语法忘记得差不多了, 一年没碰c++,两年没碰java。...bundle如果创建和使用 [/size] 加载资源的机制 http://www.cnblogs.com/BigPolarBear/archive/2012/03/28/24218...
    [size=medium]=。=

    c++的语法忘记得差不多了, 一年没碰c++,两年没碰java。
    关于objc的摘抄数量68,和c/c++持平,可惜还没什么建树。


    bundle的作用
    bundle如果创建和使用

    [/size]

    加载资源的机制
    http://www.cnblogs.com/BigPolarBear/archive/2012/03/28/2421802.html
    制作与应用
    展开全文
  • App Bundle

    2019-05-05 06:24:34
    App bundle 总结 1 简介 https://developer.android.com/platform/technology/app-bundle 官网列举的采用app bundle技术的应用: 2 Getting started Download Android Studio 3.2 or higher—it's the ...

    App bundle 总结

    1  简介

    https://developer.android.com/platform/technology/app-bundle

    官网列举的采用app bundle技术的应用:

    2 Getting started

    1. Download Android Studio 3.2 or higher—it's the easiest way to add dynamic feature modules and build app bundles.
    2. Add support for Dynamic Delivery by including a base module, organizing code and resources for configuration APKs, and, optionally, adding dynamic feature modules.
    3. Build an Android App Bundle using Android Studio. If you're not using the IDE, you can instead build an app bundle from the command line.
    4. Test your Android App Bundle using bundletool to generate APKs from your app bundle and deploy them to a connected device.
    5. Enroll into app signing by Google Play. Otherwise, you can't upload your app bundle to the Play Console.
    6. Upload your app bundle to the Play Console. You can then use the Play Console's new internal test track to quickly test downloading your app via Dynamic Delivery.

     

     

    https://android.jlelse.eu/a-practical-guide-to-android-app-bundle-for-beginners-7e8d93831828

     

    2.2 添加支持

    When downloading dynamic feature modules on demand, devices running Android 6.0 (API level 23) and lower require the app to restart before completing installation of the new modules. However, if you want to be able to access the downloaded module’s code and resources immediately after it’s downloaded, you should include support for the SplitCompat library in your manifest. To learn more, read Access code and resources from downloaded modules.

     

    2.2.1 添加Play core 依赖

    implementation 'com.google.android.play:core:1.4.1'

    2.2.2 发起需求模块请求

    // Creates an instance of SplitInstallManager.
    
    SplitInstallManager splitInstallManager =
    
        SplitInstallManagerFactory.create(context);
    
    
    
    // Creates a request to install a module.
    
    SplitInstallRequest request =
    
        SplitInstallRequest
    
            .newBuilder()
    
            // You can download multiple on demand modules per
    
            // request by invoking the following method for each
    
            // module you want to install.
    
            .addModule("pictureMessages")
    
            .addModule("promotionalFilters")
    
            .build();
    
    
    
    splitInstallManager
    
        // Submits the request to install the module through the
    
        // asynchronous startInstall() task. Your app needs to be
    
        // in the foreground to submit the request.
    
        .startInstall(request)
    
        // You should also be able to gracefully handle
    
        // request state changes and errors. To learn more, go to
    
        // the section about how to Monitor the request state.
    
        .addOnSuccessListener(sessionId -> { ... })
    
        .addOnFailureListener(exception -> { ... });

     

    延迟请求

    // Requests an on demand module to be downloaded when the app enters
    
    // the background. You can specify more than one module at a time.
    
    splitInstallManager.deferredInstall(Arrays.asList("promotionalFilters"));

    2.2.3 监听请求结果

    // Initializes a variable to later track the session ID for a given request.
    
    int mySessionId = 0;
    
    
    
    // Creates a listener for request status updates.
    
    SplitInstallStateUpdatedListener listener = state -> {
    
        if (state.sessionId() == mySessionId) {
    
          // Read the status of the request to handle the state update.
    
        }
    
    };
    
    
    
    // Registers the listener.
    
    splitInstallManager.registerListener(listener);
    
    
    
    ...
    
    
    
    splitInstallManager
    
        .startInstall(request)
    
        // When the platform accepts your request to download
    
        // an on demand module, it binds it to the following session ID.
    
        // You use this ID to track further status updates for the request.
    
        .addOnSuccessListener(sessionId -> { mySessionId = sessionId; })
    
        // You should also add the following listener to handle any errors
    
        // processing the request.
    
        .addOnFailureListener(exception -> {
    
            // Handle request errors.
    
        });
    
    
    
    // When your app no longer requires further updates, unregister the listener.
    
    splitInstallManager.unregisterListener(listener);

     

    1 错误处理

    splitInstallManager
    
        .startInstall(request)
    
        .addOnFailureListener(exception -> {
    
            switch (((SplitInstallException) exception).getErrorCode()) {
    
                case SplitInstallErrorCode.NETWORK_ERROR:
    
                    // Display a message that requests the user to establish a
    
                    // network connection.
    
                    break;
    
                case SplitInstallErrorCode.ACTIVE_SESSIONS_LIMIT_EXCEEDED:
    
                    checkForActiveDownloads();
    
                ...
    
        });
    
    
    
    void checkForActiveDownloads() {
    
        splitInstallManager
    
            // Returns a SplitInstallSessionState object for each active session as a List.
    
            .getSessionStates()
    
            .addOnCompleteListener( task -> {
    
                if (task.isSuccessful()) {
    
                    // Check for active sessions.
    
                    for (SplitInstallSessionState state : task.getResult()) {
    
                        if (state.status() == SplitInstallSessionStatus.DOWNLOADING) {
    
                            // Cancel the request, or request a deferred installation.
    
                        }
    
                    }
    
                }
    
            });
    
    }

    2 状态监听

    @Override
    
    public void onStateUpdate(SplitInstallSessionState state) {
    
        if (state.status() == SplitInstallSessionStatus.FAILED
    
            && state.errorCode() == SplitInstallErrorCode.SERVICE_DIES) {
    
           // Retry the request.
    
           return;
    
        }
    
        if (state.sessionId() == mySessionId) {
    
            switch (state.status()) {
    
                case SplitInstallSessionStatus.DOWNLOADING:
    
                  int totalBytes = state.totalBytesToDownload();
    
                  int progress = state.bytesDownloaded();
    
                  // Update progress bar.
    
                  break;
    
    
    
                case SplitInstallSessionStatus.INSTALLED:
    
    
    
                  // After a module is installed, you can start accessing its content or
    
                  // fire an intent to start an activity in the installed module.
    
                  // For other use cases, see access code and resources from installed modules.
    
    
    
                  // If the request is an on demand module for an Android Instant App
    
                  // running on Android 8.0 (API level 26) or higher, you need to
    
                  // update the app context using the SplitInstallHelper API.
    
            }
    
        }
    
    }

    3 用户确认

    @Override void onSessionStateUpdate(SplitInstallSessionState state) {
       
    if (state.status() == SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION) {
           
    // Displays a dialog for the user to either “Download”
            // or “Cancel” the request.
            splitInstallManager.startConfirmationDialogForResult(
              state,
             
    /* activity = */ this,
             
    // You use this request code to later retrieve the user's decision.
              /* requestCode = */ MY_REQUEST_CODE);
        }
        ...
     }

    4

    2.2.4 Immediately access modules

    需要SplitCompat Library 资源

    整体配置

    方式1:

    声明 SplitCompatApplication

    <application
        ...
       
    android:name="com.google.android.play.core.splitcompat.SplitCompatApplication">
    </application>

    方式2:

    public class MyApplication extends SplitCompatApplication {
    
        ...
    
    }

     

     

    动态模块下载完后立即可以访问。

     

    单独配置组件Activity或者Service

    重载attachBaseContext

    @Override
    
    protected void attachBaseContext(Context base) {
    
        super.attachBaseContext(base);
    
        // Emulates installation of future on demand modules using SplitCompat.
    
        SplitCompat.install(this);
    
    }

    访问下载的模块资源:

    需要先刷新app 的context

    case SplitInstallSessionStatus.INSTALLED:
    
                    Context newContext = context.createPackageContext(context.getPackageName(), 0);
    
                    // If you use AssetManager to access your app’s raw asset files, you’ll need
    
                    // to generate a new AssetManager instance from the updated context.
    
                    AssetManager am = newContext.getAssets();
    
            }

    新启动的模块不需要:

     

    加载so文件:

    public void onStateUpdate(SplitInstallSessionState state) {
    
        if (state.sessionId() == mySessionId) {
    
            switch (state.status()) {
    
                case SplitInstallSessionStatus.INSTALLED:
    
                    // Updates the app’s context as soon as a module is installed.
    
                    Context newContext = context.createPackageContext(context.getPackageName(), 0);
    
                    // To load C/C++ libraries from an installed module, use the following API
    
                    // instead of System.load().
    
                    SplitInstallHelper.loadLibrary(newContext, “my-cpp-lib”);
    
                    ...
    
            }
    
        }
    
    }

     

    2.2.5 管理安装的模块

    Set<String> installedModules = splitInstallManager.getInstalledModules();

     

    卸载模块:

    // Specifies two dynamic feature modules for deferred uninstall.
    
    splitInstallManager.deferredUninstall(Arrays.asList("pictureMessages", "promotionalFilters"));

    3 API

    5个包:

     

    3.1 com.google.android.play.core.splitinstall

    安装动态模块及设置监听

    3.2 com.google.android.play.core.splitcompat

    两个类,调用可以使应用不必重启即可访问动态下载的模块:

    SplitCompat    

    SplitCompatApplication 

    展开全文
  • 探索 Android App Bundle

    千次阅读 2019-04-22 23:17:17
    原文链接 Exploring the Android AppBundle,作者Joe Birch。 目录 App bundle 格式 拆分 APKs 构建和分发 Android App Bundle Bundle 工具 动态服务功能 动态提供功能 我实际会节省多少大小? 今年...

    原文链接 Exploring the Android App Bundle,作者 Joe Birch

    目录

    App bundle 格式

    拆分 APKs

    构建和分发 Android App Bundle

    Bundle 工具

    动态服务功能

    动态提供功能

    我实际会节省多少大小?


     

    今年(2018年)在 I/O 上宣布了大量令人兴奋的事情 - 我最关注的一件事是新的 app bundle 格式。 这种格式不仅为我们的应用程序提供了新的上传格式,而且还有助于影响我们以模块化格式构建和结构化应用程序的方式。在这篇文章中,我想深入了解 Android App Bundle,以便我们可以全面了解它是什么,它的工作方式以及我们如何在我们自己的应用程序中添加对它的支持。

    正如我上面提到的,我很高兴听到这种称为 App Bundle 的新上传格式。 虽然此 bundle 仍包含我们的应用程序代码和资源文件,但最大的区别在于构建 APKs 的责任转移到了 Google Play 上。 从此,新的 Dynamic Delivery 可用于创建满足用户设备要求的优化了的 APKs,并在运行时传送以进行安装。

    但为什么我们要考虑使用 Android App Bundle 呢?

    • 首先,该方法为您的代码库提供了一个干净且分离的结构。 由于 bundles 的工作方式(尤其是动态传送方式,我们稍后会介绍),按功能进行模块化将成为您应用的一部分。 这类似于 Instan tapps 中的模块化方法或一般的按功能模块化的方法。无论如何,这有助于解耦应用程序的不同部分,并有助于使您的代码库更易于使用。
    • 以前针对不同的 API 版本,设备类型等等,我们可能需要构建多个 APKs -  Android App Bundles 意味着我们现在可以只使用我们所有的应用程序资源上传单个工件,工具将处理需要构建并并传送给我们的用户的东西。 这基本上为我们自动化了这个过程,意味着我们可以将重点转移到我们开发过程的其他部分。
    • 因为 App Bundle 将针对特定设备及其配置构建 APK,这意味着所传送的 APKs 通常具有较小的体积。 这实际上取决于您的应用程序,因为主要的节省将来自密度/本地特定资源和任何其他未使用的代码。App Bundles 的早期采用者节省的一些体积显示了一些很好的成果:

     

    • App bundles 向我们介绍了一种称为 Dynamic Delivery 的新概念。 这允许我们的应用程序为用户提供新功能,并允许它们在运行时下载和安装这些新功能来作为我们应用程序的扩展。 这使我们能够缩小应用程序的初始大小,并仅向可能实际使用它们的用户提供这些附加功能。
    • 很快,app bundle 格式将支持 bundles 的 instant enable - 这意味着用户将能够立即启动我们的功能模块而无需安装我们的应用程序,类似于 instant apps 当前的工作方式。

    考虑到所有这些,让我们深入了解 app bundle 格式以及围绕它的所有概念吧!

    注意:要遵循本文的任何 IDE 部分,您需要运行 Android Studio 3.2。 

    App bundle 格式

    在我们开始深入了解 app bundle 之前,了解这种格式非常重要。 app bundle 由 zip 存档组成,其中包含组成 bundle 的文件集合。 虽然这些文件是在我们熟悉的 APKs 中找到的文件,但它的目的与 APK 不同。

     

    APK 是我们可以直接向我们的用户设备提供服务的东西,而另一方面,App Bundle 是一种发布格式,无法单独安装到设备上。虽然它们确实有相似之处,但 app bundle 确实包含一些我们在 APKs 中找不到的内容。 例如,bundles 中的元数据文件被用来构建提供给我们用户的 APKs  - 这些文件不会包含在 APKs 本身中。 虽然您可能已经熟悉 app bundle 中的大部分内容,但还是让我们来看看典型的 app bundle 可能包含的内容:

    • manifest.xml — 就像您在 APKs 中找到的那样,每个 app bundle 都有一个清单文件。然而,与 APK 不同,它们不以二进制格式存储 - 它被编译成协议缓冲区格式,这使得工具在需要时更容易转换。
    • res / assets / libs — 所有 resources,assets 和native libraries 的存储方式与 APK 相同。 这里唯一的区别是,作为最后一点,任何资源文件也将以协议缓冲区格式存储。
    • resources.pb —类似于可以在我们当前的 APK 文件中找到的 resource.arac 文件,resources.pb 文件是一个资源表,其中描述了我们的应用程序内部存在的资源和目标的细节。.pb 扩展名是由协议缓冲区格式生成的,该格式用于在将 app bundle 转换为 APK 中使用的二进制格式之前对其进行转换。
    • assets.pb — 这相当于应用程序 assets 的资源表,只有在应用程序中使用 assets 时才会出现。
    • native.pb — 这相当于 native libraries 的资源表,只有在应用程序中使用 native libraries 时才会出现。

    这里提到的最后 3 个文件是 App Bundle 的关键部分,因为这些表用于描述我们的应用程序的目标。这是动态传送中的关键概念,因为它用于描述我们所服务的设备和/或用户的类型,这使我们能够根据此信息提供特定的资源构建。

    这些 resource,assets  和 native 表都使用我们在应用程序中已经熟悉的信息来向用户提供内容。 我们熟悉使用  drawable-hdpi, lib/armeabi-v7a 或  values-es 等目录来针对特定用户并提供特定资源 - app bundle 在将特定资源定位到用户和设备时使用完全相同的方法。 因此,在组织这些事情时,我们不需要做任何不同的事情。


    拆分 APKs

    在 Android lollipop 中,我们看到一个名为 Split APKs 的功能被添加到了平台上。 这允许将多个 APKs 添加到设备,同时仍然表现为他们是单个 app 的一部分。 这些可以作为不同的组合安装在不同的设备上 - 同时仍然作为单个 APK 出现。

    这些拆分 APKs 具有与 APK 完全相同的格式,同时彼此共享相同的包名和版本号。 App Bundle 格式用于生成这些拆分 APKs,而这些 APKs 又可以提供给我们的用户设备。 首先,App Bundle 用于分析其所有资源,以查找所有设备配置共有的部分 - 这将是清单文件,dex 文件以及任何其他相同的部分,无论设备,架构还是正在使用的语言环境。这些公共部分将构成我们应用程序的基础 APK,然后,将使用拆分 APKs 为不同类型的配置创建拆分。

    然后,将生成配置拆分,以便能够为用户提供满足其设备设置要求的拆分 apks 集合:

    • 首先,将分析每种支持的屏幕密度,并为每个屏幕密度创建拆分 APK,这些将包含特定于该密度的所有资源。
    • 然后将为每个 native 架构生成不同的拆分 APK
    • 最后,将为应用程序的每个支持的区域设置生成不同的拆分 APK。

     

    因此,当用户使用我们的应用程序时,这个拆分 APKs 的子集将被传送到他们的设备。 这比当前为每个用户提供每个配置的配置更有效,因为大多数用户可能不会使用当前正在传送给他们设备的大量资源。 为了正确看待这一点,下面显示了三种不同的配置,可以提供给三个不同的用户 - 只提供他们需要的资源:

     

    如果用户在任一时刻更改其设备配置(例如添加另一种语言选项),则 play store 将识别这种情况,并尝试为在其设备上使用 split APKs 的所有应用程序下载新的配置拆分。如果设备当时不在线,那么下一次有机会时就会这样做。

    现在看来,虽然拆分 APKs 仅在 Lollipop  及更高版本上支持,app bundle 仍然有助于为使用早期版本的 Android 设备节省大小。 不再生成拆分,而是将创建独立的 APKs,以匹配架构和设备密度的不同组合的矩阵。在这种方法中,所有语言都包含在每个 APK 中,因为矩阵会因太多不同的组合而变得太大。对于这些 pre-L 设备,将为给定设备选择最合适的 APK 并将其提供给用户。

     

    正如您从App Bundle 到目前为止所看到的,无论我们支持哪种 SDK 版本,我们都可以在应用程序大小方面节省成本。 这里最棒的是,作为开发人员,我们不需要担心这个过程涉及的任何细节。 我们只需要上传一个 app bundle,Google Play 就会生成正确的 APK 拆分,然后选择要投放到每个设备的正确的 APKs。

     


    构建和分发 Android App Bundle

    在从我们的项目构建 app bundle 时,我们可以直接从 Android Studio 执行此操作。 这可以直接从 Build 菜单中完成,选择 Generate Signed Bundle / APK  - 从这里您将看到以下对话框:

     

    此时,我们可以选择构建 Android App Bundle 或 APK。选择这些选项之一将带我们进入 keystore selection/creation 对话框,然后向导将从中构建所需的选择。

    如果我们在此处构建 app bundle,则将生成 .aab 文件,这是代表 app bundle 的格式。 除了在 IDE 中使用此向导构建 App Bundle 之外,我们还可以从命令行创建 app bundle - 这对于 CIs 或喜欢使用命令行工作的人很有用。

    ./gradlew modulename:assemble
    
    ./gradlew modulename:assembleVariant

    在构建你的 bundle 时,默认情况下会生成所有拆分。 但是在 build.gradle 文件的 android 块中,您可以声明将生成哪些拆分:

    bundle {
            language {
                enableSplit = false
            }
            density {
                enableSplit = true
            }
            abi {
                enableSplit = true
            }
        }

    默认情况下,这些属性将设置为 true。 但是,将一项设置为 false 将意味着不支持指定 bundle 的配置,导致该属性的资源将打包到基本 APK 和所提供的任何动态功能 APK 中。

    一旦你构建了你的 App Bundle,就可以将其简单地上传到 play 控制台。 为了能够通过 Play Strore 分发 app bundles,您首先需要注册 Google Play 应用程序签名。 因为工具会为您生成不同的 APK 拆分,所以它还需要为它们签名的功能 - 这是必需的,如果没有它,您将无法使用 app bundles。

    现在我们已经通过 Android Studio(或命令行)构建了我们的 app bundle,我们可以将其上传到 Play Console 以准备分发。 如果您直接进入发布页面,就像您对 APK 做的一样,您会注意到您还可以通过相同的上传区域上传 App Bundle:

     

    上传 bundle 后,您将能够看到 Android App Bundle 已添加到上传区域下方的组件列表中。 展开我们刚上传的 Android App Bundle 将向您显示 APK 所做的所有信息,除了这次我们可以看到一个 Explore App Bundle 按钮:

     

    我上传 bundle 的 Application 仅支持单个区域设置(仅作为示例),但确实支持一系列不同的屏幕密度。 因此,App Bundle Explorer 向我们显示了将从给定 app bundle 中提供的不同设备配置 APKs 的细分。从这里我们还可以下载不同的 APK 用于测试目的,以及查看每个 APK 配置将提供给的设备。

    您会注意到,在顶部,我们还显示了使用 App Bundle 格式而非标准 APK 上传方法的大小节省值。这在应用程序之间会有所不同,因为这只是一个示例应用程序,节省的成本可能无法真正代表您在自己的应用程序所看到的内容。

     

    Bundle 工具

    现在,在将 App Bundle 上传到 Google Play Store 之前,对 bundle 进行一些测试非常重要。虽然我们可以使用内部测试跟踪来执行此操作,但我们也可以在本地对其进行全面测试,以确保一切按预期工作。为此我们可以使用 bundletool ,这将使我们的这个过程非常简单。 我们的 IDE 和 Google Play 使用此工具来构建我们的 bundle 以及将其转换为不同的配置拆分,因此我们将在本地看到的是用户将获得的服务的真实表示。

    当我们运行 bundle 工具时,它将根据我们的应用程序配置生成一组 APKs。为了解决这个问题,让我们为 bundle 支持的所有不同配置创建一组 unsignedAPKs :

    bundletool build-apks --bundle=/Users/joebirch/releases/sample.aab --
    output=/Users/joebirch/releases/sample.apks

    注意:如果您希望运行相同的任务但生成签名的 APKs,则可以通过将 keystore 信息添加到命令来执行此操作:

    bundletool build-apks --bundle=/Users/joebirch/releases/sample.aab --output=/Users/joebirch/releases/sample.apks
    --ks=/Users/joebirch/some_keystore.jks
    --ks-pass=file:/Users/joebirch/some_keystore.pwd
    --ks-key-alias=SomeAlias
    --key-pass=file:/Users/joebirch/some_key.pwd

    现在我们已经生成了这些 APKs,我们希望将它们提供给本地设备- bundetool 可以为我们完成这项工作。

    bundletool install-apks --apks=/Users/joebirch/releases/sample.apks

    假设我们连接的设备至少运行 Android 5.0。当我们运行此命令时,Bundletool 会将 base APK 以及任何动态功能和配置 APKs 推送到特定于该设备配置的设备 - 与 Play Store 给用户提供应用程序的方式相同。如果我们连接不同的设备,例如使用不同的密度/区域设置,则会向该设备提供一组不同的配置APKs。如果连接的设备在 Android 5.0 下运行,则最适合的 multi-APK 将被安装到设备上。处理多个设备时,您可以使用 --device-id=serial-id 来描述应用程序应该安装到那个设备。

    当bundletool 为连接的设备生成已安装的内容时,您可以检索设备规范 JSON 格式。然后,可以使用它从生成的 APKs 中提取特定的APK。首先,我们需要运行命令:

    bundletool get-device-spec

    现在我们已经为特定的设备配置提供了这个 JSON 文件,我们可以继续使用额外的特定配置来拆分:

    bundletool extract-apks
    --apks=/Users/joebirch/releases/someApkSet.apks
    --output-dir=/Users/joebirch/releases/device_APK_set.apks
    --device-spec=/Users/joebirch/releases/some_configuraton.json

    您还可以手动创建自己的设备配置 JSON 文件,并用它来提取特定配置的 APK。这对于测试您可能无法专门访问的设备配置非常有用。

    {
      "supportedAbis": ["arm64-v8a"],
      "supportedLocales": ["en", "es"],
      "screenDensity": 640,
      "sdkVersion": 21
    }

    动态服务功能

    App Bundle 的另一个关键部分就是所谓的 Dynamic Delivery。此功能允许您定义首次安装应用程序时可能不需要的模块。在我们的项目中,我们可以定义这些模块,然后在需要时使用新的 Play Core Library 按需安装。这可能是一项并非您的应用程序的所有用户都可以使用的功能,或者可能不是核心功能。 同样,这可以从初始下载中节省大小,Google Play 可以在需要时为我们提供 Dynamic Feature。

     

    为了能够添加对此的支持,让我们快速运行一下在应用程序中创建 Dynamic Feature Module。我们可以通过右键单击项目的根模块并选择 New Module  来转到 Create New Module 向导来开始。从这里我们可以选择 Dynamic Feature Module 并点击 Next

     

    现在我们需要选择应用程序的 Base 模块 - 这将是此 Dynamic Feature Module 将依赖的可安装模块。填写完所需信息后,系统将提示我们命名模块,然后我们可以完成 Dynamic Feature 模块将被添加到的位置的设置,并将其添加到我们的应用程序中。

    一旦你创建了这个模块,那值得快速浏览一下。这是为了让您了解 Dynamic Feature Module 的配置差异,了解工作原理总是很好的,如果您将来需要转换模块,那么您就知道需要添加哪些信息。

    如果打开 module build.gradle 文件,则会注意到使用的插件不同:

    apply plugin: 'com.android.dynamic-feature'

    与我们可能看到的用于 instant apps 的功能模块略有不同,此插件是您的模块被归类为动态功能模块所必需的。 同时在此文件中您应该知道 dynamic-feature build.gradle 文件没有使用的一些属性 - 例如,versionCode,vesionName,minification 和签名属性都取自基本模块。

    接下来,如果打开您的基础 modules build.gradle 文件,您会注意到我们的 dynamic feature 已添加到一个 dynamicFeatures 属性数组中:

    dynamicFeatures = [":first-dynamic-feature"]

    这是声明可用于您的应用程序的动态功能,每当您添加对新动态功能的支持时,都必须更新这些功能,以便您的 base module 了解它们。最后,如果打开动态功能模块,则可以打开该模块的清单文件以查找以下内容:

     
    <manifest xmlns:dist="http://schemas.android.com/apk/distribution"
        package="co.joebirch.first_dynamic_feature">
    
        <dist:module
            dist:onDemand="true"
            dist:title="@string/title_first_dynamic_feature">
            <dist:fusing include="true" />
        </dist:module>
    </manifest>
     
    • onDemand —如果该属性设置为 true,则该模块将可用于按需下载。 设置为 false 时,将在用户首次下载并安装应用程序时下载动态功能。
    • title — 当用户确认下载模块时,title 将用于标识模块。此字符串资源应存储在应用程序的 resources 中,以便可以为应用程序支持的不同语言环境进行翻译。
    • fusing include — 将此属性设置为 true 意味着较旧的设备(4.4 及更低版本)将能够以 multi-APKs 的形式接收这些动态功能。要使用此功能,您必须启用 onDemand 属性。

    动态提供功能

    现在我们已经为应用程序添加了 Dynamic Feature Module,我们希望在用户请求时将其实际地提供给用户。为此,我们将使用 Play Core library,它为我们提供了这样做的功能。该库允许用户打算与可能尚未安装的功能进行交互,此时我们的应用程序将请求该功能,下载该功能,然后在安装后处理其状态。

     

    要开始使用此功能,我们需要首先通过依赖项将 play 核心库添加到项目中:

    implementation 'com.google.android.play:core:1.3.4'

    现在我们可以使用这个库了,我们需要在适当的地方使用它。要在运行时下载动态功能,我们将使用 SplitInstallManager 类。同时我们的应用程序位于前台,这将用于请求动态功能,然后下载以进行安装。

    val splitInstallManager = SplitInstallManagerFactory.create(this)

    现在我们有了这个类,我们将创建一个 SplitInstallRequest 实例来下载我们的模块:

    val request = SplitInstallRequest
            .newBuilder()
            .addModule("someDynamicModule")
            .build()

    此实例将包含将用于从 Google Play 请求我们的动态功能模块的请求信息。在该请求中,我们可以声明我们想要请求的多个模块,这可以通过简单地链式调用 request builder 的多个 addModule() 来完成。

    最后,我们将使用 install manager 实例来运行我们刚刚创建的请求。 这里我们将在 manager 上使用 startInstall() 函数,传入我们之前创建的请求,并在安装完成,成功或失败时添加回调,以便相应地处理 UI。

    splitInstallManager
            .startInstall(request)
            .addOnSuccessListener {  }
            .addOnFailureListener {  }
            .addOnCompleteListener {  }

    这里的 stateInstall 函数调用将尽快触发安装过程。但是,如果您希望推迟应用程序已经后台运行的安装过程,则可以使用 deferInstall() 调用来替代执行此操作。

    当您调用这些函数中的任何一个时,将返回一个 Int 值,该值表示拆分安装的会话 ID。如果在请求安装期间的任何时候你想取消它,那么你可以通过调用 cancelInstall() 函数,传入相应请求的会话 ID 来实现。

    在安装过程中,可能会出现一系列不同的错误,让我们快速了解一下这些可能是什么错误:

    现在,当此请求发生时,我们可能会使用任何形式的UI覆盖,例如 Billing Library 或其他 Google Play 集成。因此,在下载和安装动态功能时,用户了解应用程序中发生的情况是非常重要的 - 为此,我们可以使用SplitInstallStateUpdatedListener ,这将允许我们监视请求的状态。

    val stateListener = SplitInstallStateUpdatedListener { state ->
        when (state.status()) {
            PENDING -> { }
            DOWNLOADING -> { }
            DOWNLOADED -> { }
            INSTALLED -> { }
            INSTALLING -> { }
            REQUIRES_USER_CONFIRMATION -> { }
            FAILED -> { }
            CANCELING -> { }
            CANCELED -> { }
        }
    }
    splitInstallManager.registerListener(stateListener)

    在这,您可以看到正在被定义的侦听器的实例,以及安装可能处于的不同状态 - 您应该在应用程序中使用它来处理 UI。例如,您可能希望显示某种形式的进度条以让用户知道这些状态正在发生,但是当进程通过每个状态传播时,要更改使用的消息。

    拆分安装可以包含一系列不同的状态,让我们快速查看它们都是什么:

    • CANCELED — 已取消拆分 APK 的下载
    • CANCELING — 当前正在取消拆分 APK 的下载
    • DOWNLOADED — 拆分 APK 已下载,但目前尚未安装
    • DOWNLOADING — 当前正在下载拆分 APK
    • FAILED — 下载或安装拆分 APK 失败
    • INSTALLED —拆分 APK 的安装已完成,可与应用程序一起使用。
    • INSTALLING — 当前正在安装拆分 APK
    • PENDING — 拆分 APK 的下载当前处于挂起状态
    • REQUIRES_USER_CONFIRMATION — 由于拆分 APK 的大小太大,因此下载该apk需要用户确认。
    • UNKNOWN —当前状态未知

    一旦安装了动态功能模块,仍然可以执行一些操作来管理它们。 例如,我们可以使用 deferredUninstall() 函数卸载模块 - 传入一些我们要从应用程序的用户安装中删除的模块名称。

    splitInstallManager
            .deferredUninstall(listOf("someDynamicModule"))
            .addOnSuccessListener {  }
            .addOnFailureListener {  }
            .addOnCompleteListener {  }

    我们还可以使用 manager 实例上的 getInstalledModules() 函数检索已安装模块名称的列表,这对于在应用程序中设置任何 UI 并在执行任何删除请求之前检查模块安装状态非常有用。

    val installedModules = splitInstallManager.installedModules

    我实际会节省多少大小?

    现在,您将节省应用程序的大小这句话说得很好,但是对于您将实际节省的内容,有一些指导是很有帮助的。据 Google 称,平均而言,使用 App Bundle 格式的应用程序的大小要小 20%-这意味着每次下载或更新应用程序时,所涉及的数据传输都要少 20%。

    Google 还对 Play Store 中至少有 100 万下载量的所有应用程序进行了一些分析,他们发现:

    • 当涉及到区域设置资源所使用的资源时,语言拆分将实现 95% 以上的节省。
    • (屏幕)密度拆分有助于在支持多种密度的应用中节省高达 45% 的成本
    • 使用 native 库的应用程序在架构支持方面可以节省高达 20% 的成本

    将所有这些组合在一起后,发现如果所有这些应用程序都使用 App Bundle 格式,则每天将节省 10PB 的数据。 这是一个非常高的数据量!

    Google 还从 app bundle 格式的早期采用者那里分享了一些样本数据。例如,虽然 Twitter for Android 之前已经提供过 multi-APKs,但 app bundles 能让他们看到约 20% 的大小减少。该应用程序支持许多不同的语言和密度,这是他们的大量节省的来源。App Bundle 的使用还意味着他们不再需要为他们希望支持的配置手动创建和上传单独的 APKs,因为 App Bundle 工具将自动处理此问题。

     

    另一方面,Text Plus 应用程序不支持用于不同的配置的多个 APKs。该应用程序在不同的密度和架构方面拥有大量资源,因此 App Bundle 能让它们为其应用程序节省大约 26%。

     

    最后,当团队添加对 App Bundle 的支持时,Jamo 应用程序能够将其原始应用程序大小减半。该应用程序使用许多不同的大型 native 库来支持不同的架构 - app bundle 现在允许它们优化这些要求,以便可以向用户提供较小的 APKs。

     


    我希望通过阅读本文,您能够了解什么是 App Bundles,它们是如何工作的,以及如何将其与 Dynamic Delivery 结合起来,以改进我们为用户提供应用程序的方法。我很高兴在生产中使用 App Bundles,并进一步了解如何使用它们来改进我们的应用程序大小和传送。

    展开全文
  • 由于博主长期从事海外App的开发,所以心系谷歌爸爸的动向呀,最近谷歌爸爸推出了一个Android App Bundle的东西,据说可以压缩包体,当然这仅限于上传Google Play的应用,国内市场不支持,当然我们也可以学习谷歌爸爸...
  • 初识Android App Bundle

    千次阅读 2018-10-18 16:05:48
    注:1、本文译自...2、本文“应用(程序)束”、“应用(程序)包”等价于App bundle(s) 一、引言 本文将介绍Android App Bundles的概念以及基于优化apk集的动态交付特性 什么是Android App Bundle? And...
  • Android App Bundle是一种改进的应用程序打包方式,能大幅度减少应用体积。简而言之,可以理解Google 官方的动态发布方案。按照Google官方的说法: Android App Bundle 是一种全新的上传格式,其中包含您应用的...
  •  新的应用发布格式 Android App Bundle 是一种更有效的方式来构建和发布您的应用。Android App Bundle 让您可以更轻松地以更小的应用程序大小提供出色的体验,从而支持当今各种各样的Android设备。切换很容易。您...
  • 我正在做一个项目是做一个Android App Bundle的构建工具,模仿bundletool的功能。 有点区别是bundletool是把已经创建好的module作为输入,然后放进生成aab的相应位置,我现在做的这个构建工具是要从一开始构建aab。...
  • Android App Bundle探索

    千次阅读 2018-06-03 19:19:33
    Android App Bundle是Google最新推出的Apk动态打包,动态组件化的技术,通过一个.aab结尾的bundle文件组装一个apk来为你的设备安装。 通俗理解就是,Appbudle就是把Apk拆分成了多个积木,之前我们是把一个大而全的...
  • 构建 Android App Bundle 后,您必须测试 Google Play 使用该 Android App Bundle 生成 APK 的情形,以及这些 APK 部署到设备上之后的表现。 您应该考虑通过以下两种方式来测试 app bundle:在本地使用bundletool...
  • Android App Bundle是Google在2018年推出的Apk动态打包方式,动态组件化的技术,通过一个.aab结尾的bundle文件组装一个apk来为你的设备安装。 Appbudle就是把Apk拆分成了多个积木,之前是把一个大而全的apk装到你...
  • ——打包签名时弹窗俩个选择:Android App Bundle和APK 第一个选择是Google 推出的模式,APK容量将大大缩小,也是官方墙裂推荐的。 我觉得这个人写的挺好的可以参考这里:点击查看详情 然后【Next】 这里有俩个...
  • 背景 随着应用不断演化,功能越来越复杂,且应用针对不同屏幕设备、不同国家语言资源都打包在同一个App,导致应用...为此Google在去年Google I/O大会讲述Android引入新的App动态化框架(即Android App Bundle,缩写...
  • 在unity2017.4.x才有的Build App Bundle选项,2018.3 beta也新增了这个选项。我使用的是Unity2017.4.24f1。 下面说一下导出步骤: 1.在Build Setting中Build System 选择Gradle。这样Build App Bundle 才会出现。...
  • Failed to create IXPlaceholder for app bundle ID com.*****,找了半天发现了问题,因为我的xcode是从同事那复制粘贴过来的,看来需要自己下了,son of a bitch! 如果转载请注明转于:AirZilong的博客
  • 问题描述: Unity 开发的游戏打包apk后发布到Google Store上的时候碰到一个问题,如图: 解决方法: 在Untiy项目的PlayerSetting中进行修改,如图: 修改完成之后,重新打包即可。 已测试,成功发布。...
  • Android App Bundle(aab)与UnsatisfiedLinkError

    千次阅读 2019-08-05 08:49:42
    一.起因 所做项目因为是在Google ...所以使用了Google最新的Android App Bundle的方式进行打包,就是俗称的aab。 二.遇到的问题 在我们通过GP发布了aab之后,遇到了很多Exception: java.lang.UnsatisfiedLinkErro...
  • Android App Bundles是Android推出的一种新的App开发,编译和发布机制。本文会根据官网的介绍,结合自己的一些理解,来阐述Android App Bundles的相关概念和开发流程。
  • 1、ERROR ITMS-90164 … the bundle contains a key value that is not allowed: ‘true’ for the key ‘get-task-allow’You’re trying to up
1 2 3 4 5 ... 20
收藏数 347,159
精华内容 138,863
关键字:

app bundle