cesium 围绕_围绕可定制的交付进行导航

cesium 围绕

Co-authored by Dom Elliott and Ben Weiss

Dom Elliott Ben Weiss 合着

Android App Bundle is the new publishing format for Android apps, replacing the monolithic APK. An app bundle is not installed directly. Instead, Google Play generates optimized APKs for each device from the app bundle. Compared to a monolithic APK, the APKs generated from bundles are typically much smaller. The development experience is simpler too, you don’t have to manage and version multiple APKs for different device configurations every release, saving you a lot of time.

Android App Bundle是Android应用程序的新发布格式,代替了整体式APK。 没有直接安装应用程序捆绑包。 取而代之的是,Google Play通过应用捆绑包为每个设备生成优化的APK。 与整体式APK相比,捆绑软件生成的APK通常要小得多。 开发经验也更简单,您不必为每个版本的不同设备配置管理和版本化多个APK,从而节省了大量时间。

The momentum behind Android App Bundle is incredible. Over 450,000 apps and games on Google Play use app bundles in production, representing over 30% of active installs. Apps switching to a[[ bundles have seen, on average, a 16% size saving compared to using a universal APK. This size savings has resulted in partners seeing up to an 11% increase in installs.

Android App Bundle的发展势头令人难以置信。 Google Play上有超过450,000个应用和游戏在生产中使用应用捆绑包,占有效安装量的30%以上。 与使用通用APK相比,切换到捆绑包的应用平均可节省16%的大小。 节省的空间使合作伙伴的安装量增加了11%。

When you modularize your app you can take advantage of app bundles conditional delivery features. You can choose to deliver modules at install time based on conditions, such as a user’s country or device features. On-demand delivery means you can install and uninstall modules on the fly when your app needs them. We’ve seen partners build modules for a variety of use cases such as:

模块化应用程序时,您可以利用应用程序包的条件交付功能。 您可以选择在安装时根据条件(例如用户所在的国家/地区或设备功能)交付模块。 按需交付意味着您可以在应用程序需要时即时安装和卸载模块。 我们已经看到合作伙伴为各种用例构建模块,例如:

  • Large features that are only used by a small percentage of users

    仅一小部分用户使用的大型功能
  • Specific hardware or software capabilities such as delivering an AR module to compatible devices

    特定的硬件或软件功能,例如将AR模块交付给兼容设备
  • Specific Android versions

    特定的Android版本
  • Delivering large libraries with limited lifetime that can be installed and removed when they’re no longer needed.

    提供寿命有限的大型库,可以在不再需要它们时安装和删除它们。

These advanced features are optional, you can just use the app bundle for publishing. You can also modularize your app without using any other customizable delivery options.

这些高级功能是可选的,您可以仅使用应用程序捆绑包进行发布。 您还可以在不使用任何其他可自定义交付选项的情况下模块化您的应用程序。

This post explores in some detail the features for creating and delivering modular apps, focusing on defining module dependencies and working with app navigation. First, however, I’ll bring you up-to-date with some of the new and planned features for bundles.

这篇文章更详细地探讨了创建和交付模块化应用程序的功能,重点是定义模块依赖性以及使用应用程序导航。 但是,首先,我将为您介绍捆绑包的一些新功能和计划中的功能。

最新和最伟大的 (Latest and greatest)

Our vision for app bundles goes further. We’re working on a dynamic framework with more options.

我们对应用程序捆绑包的愿景进一步提高。 我们正在开发具有更多选项的动态框架。

These options include in-app updates, enabling you to trigger and complete updates entirely from within your app. We’ve also worked on customizable asset delivery, enabling the app bundle to include asset packs. This feature can be especially useful for games developers who want to package large game assets with their game binary as a single artifact. We further introduced several options for delivering those assets to users.

这些选项包括应用程序内更新,使您可以完全从应用程序内部触发和完成更新。 我们还致力于可定制的资产交付,使应用程序捆绑包包含资产包。 对于希望将大型游戏资产与游戏二进制文件打包为单个工件的游戏开发人员而言,此功能特别有用。 我们进一步介绍了几种用于将这些资产交付给用户的选项。

We’re introducing new features that complement this dynamic framework. For example, the app size report in the Google Play Console provides data such as app download size and size on device. It gives you size guidance when you’re using the app bundle too. Recently, we added new metrics relating to your users, and we show you the proportion of your active users who have low device storage. These users can present an uninstall risk, and optimizing your app size is one way to reduce that risk.

我们正在引入补充此动态框架的新功能。 例如,Google Play控制台中的应用程序大小报告提供了数据,例如应用程序下载大小和设备上的大小。 当您同时使用应用包时,它还会为您提供尺寸指导。 最近,我们添加了与您的用户有关的新指标,并向您显示了设备存储空间低的活动用户的比例。 这些用户可能会带来卸载风险,而优化您的应用大小是降低这种风险的一种方法。

We’ve also added a new feature to Google Play’s app signing service that enables you to upgrade your app signing key to a new cryptographically stronger signing key for new installs. This is especially useful if you created your app signing key a long time ago, and it’s not as cryptographically strong as you want it to be.

我们还为Google Play的应用签名服务添加了一项新功能,使您可以将应用签名密钥升级为新安装的,加密强度更高的新签名密钥。 如果您很久以前创建了应用程序签名密钥,并且它的加密强度不如您希望的那样,这将特别有用。

Finally, there’s internal app sharing, which makes testing app bundles and dynamic delivery easier. Internal app sharing gives you a fast way to share your apps for local testing. Using this mechanism, Google Play installs the test app on a device in the same way it is if the app were released. All you need to do is upload a bundle to Google Play, then share a URL with your testers, they then open this URL on their device to install the app. Developers using internal app sharing say it speeds up their workflows. You can make anyone at your company an uploader to internal app sharing, without giving them any other access to the Play Console.

最后,内部有应用程序共享,这使测试应用程序捆绑包和动态交付更加容易。 内部应用程序共享使您可以快速共享应用程序以进行本地测试。 Google Play使用此机制将测试应用程序安装到设备上,就像发布应用程序一样。 您需要做的就是将捆绑包上传到Google Play,然后与测试人员共享一个URL,然后他们在设备上打开此URL以安装该应用。 使用内部应用程序共享的开发人员表示,这可以加快工作流程。 您可以将公司中的任何人设为内部应用共享的上传者,而无需授予他们其他对Play控制台的访问权限。

cesium 围绕_围绕可定制的交付进行导航_第1张图片

If you have other artifacts you’ve uploaded to the Play Console, you will be able to get install links for them too. For app bundles, go to the bundle explore and switch to an old version, and you can copy an install link. Find out more about developer tools on the Play Store here.

如果您还有其他工件已上传到Play控制台,则也可以获取它们的安装链接。 对于应用程序捆绑包,请转到捆绑包浏览并切换到旧版本,然后您可以复制安装链接。 了解更多关于在Play商店的开发者工具在这里 。

Finally, we’ve added the FakeSplitInstallManager class to Play Core. This enables you to test an app with dynamic features offline. Normally, when you load an on-demand dynamic feature in your app, SplitInstallManager requests the Play Store to install the splits for that dynamic feature and you have to wait for them to load. Using FakeSplitInstallManager, your app installs the splits needed locally, offline. You don’t have to wait for Play to deliver and install the splits. This makes it easy to iterate on dynamic features early on in the development process, without needing to be online and without waiting for the Play Store. You can still switch to SplitInstallManager and do full online testing with internal app sharing when you’re ready. This is available now in the latest Play Core release.

最后,我们将FakeSplitInstallManager类添加到Play Core。 这使您可以离线测试具有动态功能的应用程序。 通常,当您在应用中加载按需动态功能时, SplitInstallManager要求Play商店安装该动态功能的拆分,而您必须等待它们加载。 使用FakeSplitInstallManager ,您的应用程序可以离线本地安装所需的拆分。 您无需等待Play交付并安装拆分。 这样一来,您就可以轻松地在开发过程的早期阶段迭代动态功能,而无需在线,也无需等待Play商店。 准备就绪后,您仍然可以切换到SplitInstallManager并使用内部应用程序共享进行完整的在线测试。 最新的Play Core版本现已提供此功能。

These testing features are all about making it easier for you to test your app bundles and dynamic delivery as part of your workflow.

这些测试功能都是为了使您更轻松地测试应用程序捆绑包和动态交付,并将其作为工作流的一部分。

Now you have an overview of the latest features in Android App Bundle let’s look more closely at features and modularize in your app.

现在,您将概述Android App Bundle中的最新功能,让我们更仔细地研究功能并在您的应用程序中进行模块化。

功能依赖功能 (Feature on feature dependencies)

Before talking about feature-on-feature dependencies let’s recap one of the key capabilities of app bundles: dynamic modules.

在讨论功能对功能的依赖关系之前,让我们回顾一下应用程序捆绑包的关键功能之一:动态模块。

cesium 围绕_围绕可定制的交付进行导航_第2张图片

Say you have an app with three different features. One of them offers camera support (green), one offers video support (orange), and the third payments support (blue). The goal of modularizing your app is to break it into dynamic features so that you have a better separation of code. Modularization into dynamic features also means that different users can get different portions of your app: user 1 may use the camera support, user 2 may be a bit more advanced and use the camera and video support, and user 3 may use the camera and payment features.

假设您有一个具有三种不同功能的应用程序。 其中一个提供相机支持(绿色),一个提供视频支持(橙色),第三个提供付款支持(蓝色)。 模块化应用程序的目标是将其分解为动态功能,以便更好地分离代码。 模块化为动态功能还意味着不同的用户可以获取应用程序的不同部分:用户1可以使用相机支持,用户2可以更高级,可以使用相机和视频支持,用户3可以使用相机和付款特征。

The advantage of this approach is that each user can get whatever parts of the app they need, and they’ll have a much smaller installed app size compared to one delivered as a monolithic APK.

这种方法的优势在于,每个用户都可以获取他们需要的应用程序的任何部分,并且与作为整体APK交付的应用程序相比,它们的安装应用程序尺寸要小得多。

Google Play stats show that for every 3 megabytes decreases app size, conversions can increase by up to 1%.

Google Play统计数据表明,每减少3 MB的应用程序大小,转化次数最多可以增加1%。

There are other advantages that you do get out of modularizing your app. The first one is faster incremental build times from the ability to build only a subset of modules. This means you spend less time building your app and more time developing it. Another advantage is the logical separation of code. For example, if one team wants to work on the camera feature and another on the video feature, there should be fewer cross-team dependencies.

从模块化的应用程序中您还可以获得其他优势。 第一个是通过仅构建模块子集的能力来加快增量构建时间。 这意味着您花费更少的时间来构建应用程序,而花费更多的时间来开发它。 另一个优点是代码的逻辑分离。 例如,如果一个团队想要处理摄像头功能而另一个团队要处理视频功能,则跨团队的依存关系应该更少。

Here at Google, we’re big believers in modular app development: it speeds up development and improves quality. A modular approach means teams work independently to build, test, and debug features without the complexity of everyone working on one big, complex app code monolith.

在Google,我们坚信模块化应用程序开发:它可以加快开发速度并提高质量。 模块化方法意味着团队可以独立工作以构建,测试和调试功能,而无需每个人都在一个庞大而复杂的应用程序代码整体上工作。

For more information check out my article Local development and testing with on-demand modules.

有关更多信息,请查看我的文章本地开发和按需模块测试 。

动态功能交付 (Dynamic feature delivery)

Once you have dynamic features in your app you get 3 methods of delivering them:

在您的应用中拥有动态功能后,您将获得3种交付方式:

  • Install time delivery, where the user installs the app and the dynamic features are automatically downloaded onto the device.

    安装时间交付,用户在其中安装应用程序,动态功能会自动下载到设备上。
  • On-demand delivery, which downloads dynamic features when the app requests them.

    按需交付,可在应用程序请求动态功能时下载。
  • Conditional delivery, which depends on the configuration of the users’ devices. For example, a device that supports AR would install an AR support dynamic feature while devices without support for AR would not.

    有条件的交付,这取决于用户设备的配置。 例如,支持AR的设备将安装AR支持动态功能,而不支持AR的设备则不会。

You can also use all of these delivery mechanisms with instant app or game delivery — this is where you deliver a small (up to 10 MB) version of your app that the user loads by selecting “Try Now” in the Play Store. However, where you mark your instant enabled dynamic features for at-install delivery these features are automatically installed when the user chooses to install the app. Also, where you mark features for on-demand delivery and you use them in your at-install delivery, you have to prompt the user to download these features from the installed app, because they won’t be automatically downloaded when the user starts using the installed app when coming from the instant app.

您还可以将所有这些交付机制与即时应用程序或游戏交付一起使用-在此处,您可以通过在Play商店中选择“立即尝试”来交付用户加载的小版本(最多10 MB)的应用程序。 但是,当您标记即时启用的动态功能以进行安装时交付时,这些功能会在用户选择安装应用程序时自动安装。 此外,在标记要按需交付的功能并在安装时交付中使用它们的位置,您必须提示用户从已安装的应用程序下载这些功能,因为当用户开始使用时不会自动下载这些功能。来自即时应用程序的已安装应用程序。

基本APK依赖性 (Base APK dependency)

Originally dynamic features depended on the base APK. So, take our app with dynamic features for camera, video, and payment. If the camera and video features relied on common image processing software, that software had to reside in the APK.

最初的动态功能取决于基本的APK。 因此,请使用具有动态功能的相机,视频和付款应用程序。 如果摄像机和视频功能依赖于常见的图像处理软件,则该软件必须驻留在APK中。

cesium 围绕_围绕可定制的交付进行导航_第3张图片

This meant that, if a user only wanted the payment feature, they still had to download the APK containing the image processing software. This placed a limitation on how far you can go with optimizing your download size.

这意味着,如果用户只想要支付功能,他们仍然必须下载包含图像处理软件的APK。 这限制了您可以优化下载大小的范围。

With Android Studio 4.0 you can define dynamic features that depend on other dynamic features. So, in the example app, you could now pull all this image processing code into the camera dynamic feature.

使用Android Studio 4.0,您可以定义依赖于其他动态功能的动态功能。 因此,在示例应用程序中,您现在可以将所有这些图像处理代码提取到相机动态功能中。

cesium 围绕_围绕可定制的交付进行导航_第4张图片

Now, users who want to use the payment feature won’t have to install an APK that includes image processing software. This means you are able to deliver a smaller APK and, hopefully, improve conversions.

现在,想要使用付款功能的用户将不必安装包含图像处理软件的APK。 这意味着您可以提供较小的APK,并希望可以提高转换率。

To start using this feature install Android Studio 4.x Canary/Beta.

要开始使用此功能,请安装Android Studio 4.x Canary / Beta 。

Once you’ve developed your features, you list them in the base app’s build.gradle file. If you’re adjusting the dependencies of existing features, you won’t need to make any changes.

一旦开发了功能,就可以在基本应用程序的build.gradle文件中列出它们。 如果要调整现有功能的依赖性,则无需进行任何更改。

// app/build.gradle
android {
    ...
    dynamicFeatures = [":camera", ":video", ":payment"]
}

Next, you define the dependencies in each of the features’ build.gradle files. If you’re adjusting the dependencies of existing features, you simply add the dependency on :camera to the video features build.gradle file.

接下来,您在每个功能的build.gradle文件中定义依赖 。 如果要调整现有功能的依赖性,只需将对:camera的依赖性添加到视频功能build.gradle文件中。

// payment/build.gradle 
dependencies {
  implementation project(':app')
}


// camera/build.gradle
dependencies {
  implementation project(':app')
}


// video/build.gradle 
dependencies {
  implementation project(':app')
  implementation project(':camera')
}

Once this is done, Android Studio parses the dependency tree ready for use in the new Android Studio Canary feature dependencies capabilities. However, before you can use those features you have to add a feature flag. To do this go to Help > Edit Custom VM Options, add rundebug.feature.on.feature to the file, save the change, and restart Android Studio.

完成此操作后,Android Studio将解析依赖关系树,以准备在新的Android Studio Canary功能依赖项功能中使用。 但是,在使用这些功能之前,必须添加功能标志。 为此,请转到帮助 > 编辑自定义VM选项 ,将rundebug.feature.on.feature添加到文件中,保存更改,然后重新启动Android Studio。

cesium 围绕_围绕可定制的交付进行导航_第5张图片

Now open Run > Edit configurations and in Run/Debug Configuration you can define various installation configurations for testing.

现在打开运行 > 编辑配置,然后在运行/调试配置中可以定义各种安装配置以进行测试。

If you select the video feature, you see that the camera feature is required by the video feature. So, when you test the video feature, Android Studio will automatically select the camera feature and install it when you run the test. Also, if you deselect the camera feature the video feature is also deselected as you don’t have the camera feature you won’t be able to use the video feature.

如果选择视频功能,则会看到视频功能需要相机功能。 因此,当您测试视频功能时,Android Studio将自动选择相机功能并在运行测试时进行安装。 另外,如果取消选择摄像头功能,则由于没有摄像头功能,也会取消选择视频功能,因此将无法使用视频功能。

Now build your app normally and upload it to the Play Console. Play then automatically serves the correct dynamic feature modules to your device.

现在,正常构建您的应用并将其上传到Play控制台。 Play会自动将正确的动态功能模块提供给您的设备。

应用导航 (App navigation)

The traditional way to navigate is using the framework APIs, which provides 2 options:

导航的传统方式是使用框架API,它提供2个选项:

  • Start an activity using an Intent, which is the easiest way to start a new screen for your app.

    使用Intent启动活动,这是为应用程序启动新屏幕的最简单方法。
  • Use the supportFragmentManager to replace fragments as you need them to navigate from one screen to the other.

    当需要片段从一个屏幕导航到另一个屏幕时,请使用supportFragmentManager替换片段。

TheJetpack navigation architecture component makes it easier to navigate your screens. This component includes the Navigation Editor, where you define destinations and then manipulate the navigation paths for these destinations. The navigation defined in Navigation Editor populates the res/navigation/graph.xml file, eliminating the need to handwrite code: although you can still make manual edits if you wish.

Jetpack导航体系结构组件使您可以更轻松地浏览屏幕。 该组件包括导航编辑器,您可以在其中定义目标,然后操纵这些目标的导航路径。 在“导航编辑器”中定义的导航将填充res/navigation/graph.xml file ,从而无需手写代码:尽管您仍然可以根据需要进行手动编辑。

You have to write a little bit of code within your layout.xml file to reference the NavHostFragment. You set it as your default fragment and reference the graph ID that you created, either manually or with the Navigation Editor.

您必须在layout.xml文件中编写一些代码来引用NavHostFragment 。 您可以将其设置为默认片段,并手动或使用“导航编辑器”引用创建的图形ID。

After changing this, you don’t have to manually start activities or interact with the fragment manager itself, because the navigation component takes care of all of this for you.

更改此设置后,您无需手动启动活动或与片段管理器本身进行交互,因为导航组件会为您处理所有这些工作。

导航动态功能 (Navigating dynamic features)

App bundles and dynamic feature modules changed the way that apps navigate from a base module to a feature. An app can have multiple dynamic feature modules, installed at install time or later using one of the customizable delivery options mentioned above. This means a module might not be installed when your app navigates to it. That causes problems for the navigation component because the library expects a module to be on device when the app navigated to it. The Dynamic Feature Navigator libraries solve this problem.

应用程序捆绑包和动态功能模块更改了应用程序从基本模块导航到功能的方式。 一个应用程序可以具有多个动态功能模块,这些模块可以在安装时或稍后使用上述自定义交付选项之一安装。 这意味着当您的应用导航到该模块时,可能未安装该模块。 这会导致导航组件出现问题,因为当应用程序导航到该组件时,库希望该组件位于设备上。 Dynamic Feature Navigator库解决了此问题。

Dynamic Feature Navigator is a set of AndroidX libraries that build on top of dynamic features, navigation components, and the Play Core library. The library is now available in Alpha, find out more in our guide here.

动态功能导航器是一组AndroidX库,它们建立在动态功能,导航组件和Play Core库的基础上。 该库现已在Alpha中可用,请在此处的指南中找到更多信息 。

To illustrate how smooth the transition from navigation to dynamic feature navigation should be let’s look at an example navigation graph and on-demand module. Here are the steps you will follow:

为了说明从导航到动态要素导航的过渡过程如何平滑,我们来看一个示例导航图和按需模块。 这是您将遵循的步骤:

  1. In your layout.xml file replace NavHostFragment with DynamicNavHostFragment, the new class that provides the base implementation and the easiest way to interact with Dynamic Feature Navigator.

    在您的layout.xml文件中,将NavHostFragment替换为DynamicNavHostFragment ,新类提供了基本实现以及与Dynamic Feature Navigator进行交互的最简单方法。

Before

之前

After

2. Make changes to your navigation graph. This process parallels the way in. which you declare module names in the build.gradle files to tell your app which modules are installed. In this case, for each feature, you add a module name and the destination of each feature so the dynamic feature navigator knows where to find and install a feature as it’s needed.

2.更改导航图。 此过程与在build.gradle文件中声明模块名称的方式相似,以告诉您的应用程序安装了哪些模块。 在这种情况下,为每个功能部件添加模块名称和每个功能部件的目的地,以便动态功能部件导航器知道在哪里可以找到和安装功能部件。


  
  

With these changes, you can navigate from a base module, download and install a new module, and launch it as required. All this without touching any other code. The navigator takes care of the installation state progress and all the intermediate states for you.

通过这些更改,您可以从基本模块导航,下载并安装新模块,然后根据需要启动它。 所有这些都无需触摸任何其他代码。 导航器会为您处理安装状态进度和所有中间状态。

Let’s take a look under the hood to see how this works. When you use the navigation component, navigate() is called, and the navigator knows how to navigate from one destination to another.

让我们来看看它的工作原理。 使用导航组件时,将调用navigation navigate() ,并且导航器会知道如何从一个目的地导航到另一个目的地。

cesium 围绕_围绕可定制的交付进行导航_第6张图片

When you’re using dynamic feature modules and they’re not installed, the navigation component does not know how to go from A to B. This challenge is solved within the dynamic feature navigator by providing an intermediate progress destination.

当您使用动态功能模块且未安装它们时,导航组件将不知道如何从A过渡到B。通过提供中间进度目标,可以在动态功能导航器中解决此难题。

This ProgressDestination checks whether a module is installed. If the module is installed, the navigator directly and transparently navigates to the destination. If the module is not installed, the dynamic feature navigator downloads and installs the feature, and then launches to the destination feature.

此ProgressDestination检查是否安装了模块。 如果安装了模块,则导航器将直接透明地导航到目标位置。 如果未安装模块,则动态功能导航器将下载并安装功能,然后启动到目标功能。

You can also customize this process using the API provided by extending the AbstractProgressFragment. You pass it a layout ID for what you want to show. Then override the onProgress function, which transparently calls down to the Play Core API so your app can display the progress to your users. There are also functions to override the progress states that you might want to handle.

您还可以使用通过扩展AbstractProgressFragment提供的API自定义此过程。 您向其传递要显示的布局ID。 然后覆盖onProgress函数,该函数透明地调用Play Core API,以便您的应用可以向用户显示进度。 还有一些功能可以覆盖您可能要处理的进度状态。

abstract class AbstractProgressFragment(layoutId: Int) {
  abstract fun onProgress(status: Int, bytesDownloaded: Long, bytesTotal: Long)
  abstract fun onCancelled()
  abstract fun onFailed(errorCode: Int)
}

To set the custom progress fragment, open the graph.xml and add the fragment’s ID as a progressFragment.

要设置自定义progress片段,请打开graph.xml并将片段的ID添加为progressFragment


  

You also have to set the progress fragment with that fragment ID, at some point within the navigation graph hierarchy, for the navigation component to catch it.

您还必须在导航图层次结构中的某个点设置带有该片段ID的进度片段,以便导航组件可以捕获它。

If customizing the progress destination is not enough, you can go even further and show installation progress using a toast like notification, or any UI of your choice.

如果自定义进度目标还不够,您可以走得更远,并使用Toast之类的通知(或您选择的任何UI)显示安装进度。

To achieve this, pass in a DynamicInstallMonitor in Extras to the .navigate() call, and check DynamicInstallMonitor.installRequired to determine whether the installation is required. If false is returned, your app can jump to the module. Otherwise, you subscribe to the status of the installation, to get live data from SplitInstallSessionStates. You also check whether the installation arrives at an end state, to find out if the installation has failed or been canceled and your app cannot proceed to the feature. To use SplitInstallSessionStates, create InstallMonitor and pass it to the DynamicExtras. These DynamicExtras then get passed into the navigate function, where you can subscribe to the live data and observe the split states.

为此,请将Extras中的DynamicInstallMonitor传递给.navigate()调用,然后检查DynamicInstallMonitor.installRequired以确定是否需要安装。 如果返回false ,则您的应用可以跳转到该模块。 否则,您订阅安装状态,以从SplitInstallSessionStates获取实时数据。 您还检查安装是否达到结束状态,以了解安装是否失败或被取消以及您的应用无法继续使用该功能。 要使用SplitInstallSessionStates ,创建InstallMonitor并把它传递给DynamicExtras 。 然后将这些DynamicExtras传递到导航功能中,您可以在其中订阅实时数据并观察拆分状态。

val extras = DynamicExtras(installMonitor = installMonitor)
navigate(destination, args, navOptions, extras)
installMonitor.status.observe(this, object : Observer {
  override fun onChanged(state: SplitInstallSessionState?) {
    …
  }
}

The dynamic feature navigator libraries are fully customizable through the AndroidX navigation-dynamic-features-core that provides all the navigator APIs and the APIs for activity navigation with dynamic features and fragmented navigation with dynamic features.

动态功能导航器库可通过AndroidX navigation-dynamic-features-core进行完全自定义,该navigation-dynamic-features-core提供所有导航器API以及用于具有动态功能的活动导航和具有动态功能的分段导航的API。

Start with the fragment version, because that gives you the easiest way to interact with the dynamic feature navigator. If you need to, you can go all the way down to the core and build a completely custom experience.

从片段版本开始,因为它为您提供了与动态功能导航器进行交互的最简单方法。 如果需要,您可以一直深入到核心,并建立完全自定义的体验。

To get started, add the dependencies to your build.gradle file:

首先,将依赖项添加到build.gradle文件中:

dependencies {
  def nav_version = "2.3.0-alpha04"
  api "androidx.navigation:navigation-fragment-ktx:$nav_version"
  api "androidx.navigation:navigation-ui-ktx:$nav_version"
  api "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"
}

And, when you find a bug or other issue in the snapshot will have a feature request, file it at goo.gle/navigation-bug.

并且,当您在快照中发现错误或其他问题时,将会提出功能请求,请将其提交到goo.gle/navigation-bug。

Play Core的Kotlin扩展库 (Kotlin extensions library for Play Core)

Not every app uses the navigation component, and also not every dynamic feature has a UI, a fragment or an activity for example. This is where the Kotlin extensions library for Play Core comes in. As it is an extension library, it doesn’t replace the main Play Core artifact but builds on top of it. It uses the same APIs underneath.

并非每个应用程序都使用导航组件,也不是每个动态功能都具有UI,片段或活动。 这是用于Play Core的Kotlin扩展库的来源。由于它是扩展库,因此它不会替代主要的Play Core工件,而是在其基础上构建的。 它在下面使用相同的API。

Building on top of the existing API, we took the opportunity to simplify it and help guide you through the correct flows and recommended patterns of API use. This is done by leveraging the power of Kotlin coroutines. To illustrate, this is the original Play Core API, and it’s asynchronous.

在现有API的基础上,我们借此机会对其进行了简化,并帮助您指导正确的流程和建议的API使用模式。 这是通过利用Kotlin协程的强大功能来完成的。 为了说明这一点,这是原始的Play Core API,并且是异步的。

manager.startInstall(request): Task

Most methods in the SplitInstallManager return immediately, with a task that sets callbacks. For example, addOnSuccessListener lets you listen for the work to be completed, so you can act after it completes. You also need to add the failure listener, where you can get exceptions and handle any failures.

SplitInstallManager中的大多数方法SplitInstallManager立即返回,并带有设置回调的任务。 例如, addOnSuccessListener允许您侦听要完成的工作,因此您可以在完成后采取行动。 您还需要添加故障侦听器,您可以在其中获取异常并处理所有故障。

So, how does this work in Play core KTX? It’s the same call, but it has a couple of differences.

那么,这在Play核心KTX中如何运作? 这是相同的调用,但是有一些区别。

cesium 围绕_围绕可定制的交付进行导航_第7张图片

First, there are no ugly callbacks. This call is sequential: it returns a result with a session ID instead of passing that through the task and callbacks. That’s because this function is actually a suspending function, so it has to run in a coroutine. It’s suspending but it’s not blocking, so it’s safe to call from the main thread. And, it returns a result that you can assign to a value.

首先,没有难看的回调。 该调用是顺序的:它返回带有会话ID的结果,而不是通过任务和回调传递该结果。 这是因为此函数实际上是一个挂起函数,因此必须在协程中运行。 它正在挂起,但没有阻塞,因此从主线程调用是安全的。 并且,它返回可以分配给值的结果。

This is implemented as an extension function on the SplitInstallManager, building on top of the existing APIs. And we use all the Kotlin syntactic sugar whenever it makes sense. In this example, we’re using default and named arguments, so it’s easier to call these methods. This works well for functions that return a single result. However, the Play Core API is much more complicated than that. This example shows the install process for a split.

这是在SplitInstallManager上的扩展功能上实现的,该功能建立在现有API的基础上。 只要有道理,我们都会使用所有Kotlin语法糖。 在此示例中,我们使用默认和命名参数,因此调用这些方法更容易。 这对于返回单个结果的函数效果很好。 但是,Play Core API比这复杂得多。 本示例显示了拆分的安装过程。

It goes through many steps and emits many status events, and a simple suspending coroutine function is not something that would work. Normally, in Play Core, you would handle it with a listener, using code similar to this:

它经过许多步骤并发出许多状态事件,并且简单的暂停协程函数无法正常工作。 通常,在Play Core中,您可以使用类似于以下代码的监听器来处理它:

// BEFORE ISSUING INSTALL REQUEST
manager.registerListener(listener)


...


val listener = SplitInstallStateUpdatedListener { state ->
  if (state.sessionId == sessionId) {
    when (state.status()) {
      // RESPOND TO PROGRESS EVENTS
    }
  }
}


...


// CLEANUP WHEN LEAVING SCOPE
manager.unregisterListener(listener)

This code leaves you to handle, for example, adding a subclass listener and providing your own status handling. Importantly, you need to clean up the listener at the right moment, whenever the listener or the object leaves the scope, to prevent memory leaks and lifecycle issues.

该代码使您可以处理例如添加子类侦听器并提供自己的状态处理。 重要的是,每当侦听器或对象离开作用域时,都需要在适当的时候清理侦听器,以防止内存泄漏和生命周期问题。

Enter an API called Flow, which is part of the Kotlin coroutines library. This example requests a flow that emits status events about the installation for splits from the Play Core API.

输入名为Flow的API,该API是Kotlin协程库的一部分。 此示例请求一个流程,该流程发出来自Play核心API的拆分安装状态事件。

viewModelScope.launch {
    manager.requestProgressFlow()
           .collect { state -> ... }
}

The collect function on Flow is also suspending, which means this will run in a coroutine. And there’s another important property of coroutines: they support cancellation. In the KTX libraries for AndroidX, you get extensions on the view models, activities, and fragments. These extensions give you scopes for running your coroutines as long as your view model (or a fragment or an activity) are active, you will keep getting events.

Flow上的collect函数也正在挂起,这意味着它将在协程中运行。 协程的另一个重要特性是:它们支持取消。 在AndroidX的KTX库中,您可以获得有关视图模型,活动和片段的扩展。 这些扩展为您提供了运行协程的范围,只要您的视图模型(或片段或活动)处于活动状态,您就将继续获取事件。

As soon as the user navigates away from that screen and the scope is canceled, we also cancel the Flow, clean up any listeners, and you will not get any more events after your lifecycle is finished. On top of that, Flow and the Kotlin coroutine libraries come with a lot of operators built-in, so you can deal with the streams of events in a nicer way.

一旦用户离开该屏幕并取消了作用域,我们还将取消Flow,清理所有侦听器,并且在生命周期结束后您将不会再收到任何事件。 最重要的是,Flow和Kotlin协程库内置了许多运算符,因此您可以更好地处理事件流。

Here, for example, I’m filtering the stream of events for only the updates about the module I’m interested in:

例如,在这里,我仅针对有关我感兴趣的模块的更新来过滤事件流:

viewModelScope.launch {
    manager.requestProgressFlow()
           .filter { "myModule" in it.moduleNames }
           .collect { state -> … }
}

This is a much better way of working with this API.

这是使用此API的更好方法。

The module installation process is quite complicated — it goes through many different states. How do you know, as a developer, which ones are important, which ones you need a handle for the installation to be able to continue, and which ones simply affect the UI, but are not essential for the installation to complete?

模块安装过程非常复杂-它经历许多不同的状态。 作为开发人员,您如何知道哪些是重要的,哪些需要安装的句柄才能继续进行,以及哪些仅影响UI,但对于完成安装不是必不可少的?

Here’s a convenience function, that takes lambdas, and creates the listener for you.

这是一个便捷功能,它需要lambda并为您创建侦听器。

private val listener = SplitInstallStateUpdatedListener(
    onRequiresConfirmation = { state -> // ← REQUIRED ARGUMENTS
     // HANDLE CONFIRMATION DIALOG
    },
    onInstalled = {
       // HANDLE INSTALLED STATE
    },
    onDownloading = { state -> // ← OPTIONAL ARGUMENTS
        // SHOW PROGRESS
    },
    …
)

For the mandatory states that you need to handle, such as user confirmation for downloading a large module, you need to provide these arguments. And of course, all the other states are optional arguments, so you can handle them as well and show it in your UI.

对于您需要处理的强制性状态,例如下载大型模块的用户确认,您需要提供这些参数。 当然,所有其他状态都是可选参数,因此您也可以处理它们并将其显示在UI中。

最后的话 (Final words)

Modularizing your app simplifies development and can help you raise the quality bar on your code. Coupling modularization with Android App Bundles means that you can take advantage of dynamic features to deliver users the optimal code for the features they want to use.

对应用程序进行模块化可以简化开发,并可以帮助您提高代码质量。 借助Android App Bundles进行模块化模块化,意味着您可以利用动态功能为用户提供他们想要使用的功能的最佳代码。

The new features covered in this post enable you to achieve greater code size optimization with dependent dynamic features. The new navigation and Kotlin features simplify the coding needed to ensure your app navigation works seamlessly with dynamic features.

这篇文章中介绍的新功能使您可以通过依赖的动态功能实现更大的代码大小优化。 新的导航和Kotlin功能简化了所需的编码,以确保您的应用程序导航与动态功能无缝结合。

Taking full advantage of the dynamic features of app bundles to ensure you minimize the download and on-device size of your apps and games can help you achieve better conversion and reduce the likelihood of uninstalls.

充分利用应用程序捆绑包的动态功能,以确保最小化应用程序和游戏的下载以及设备上的设备大小,可以帮助您实现更好的转换并减少卸载的可能性。

To learn more, see Android App Bundle on the Android Developers website.

要了解更多信息,请参阅Android Developers网站上的Android App Bundle 。

翻译自: https://medium.com/androiddevelopers/navigating-your-way-around-customizable-delivery-e7a882390aa

cesium 围绕

你可能感兴趣的:(cesium 围绕_围绕可定制的交付进行导航)