Android即时应用:如何创建可通过URL地址访问的模块?

25

谷歌最近更新了有关即时应用的文档:准备你的应用程序

其中大部分内容都很清晰,除了第三点:如有必要,请重构您的应用

他们建议为浏览、搜索、物品详情和结账等零售模块进行操作。

问题:我如何将应用程序拆分为完全功能和URL可寻址的模块?

这里存在几个问题:

  • 如果我们使用诸如Dagger、ButterKnife等库,则所有模块都会依赖于其他模块
  • 如果我们的模块包含所需的(视图),则应如何实现从另一个模块到另一个视图的过渡而不导入此模块?

是否有人能为此提供帮助?谢谢!


如果我们使用像Dagger、ButterKnife这样的库,所有模块都会依赖于其他模块吗?- 绝不是。为什么要这样呢?我最近在一个大型代码库中进行了这样的重构,其中广泛使用了Dagger和ButterKnife,并且可以说 - 这对我来说不是问题。请查看我的答案以获取更多详细信息,并让我知道您是否有任何疑问。 - Idolon
5个回答

4

使用以下步骤可以轻松完成Instant Apps所需的模块分离:

  1. 创建一个共享模块,其中包含应跨功能模块共享的代码和资源。
  2. 为每个主要功能创建多个功能模块(例如Google提供的示例: 浏览,搜索,项目详情和结算)。这些模块可以依赖于步骤1中创建的共享模块,但它们不应该彼此了解。
  3. 为了从不同的模块启动活动,请使目标活动具有URL地址,并通过隐式意图启动它。Google 建议 使用 App Links 来实现。
  4. 要构建常规Android应用程序,请创建一个依赖于功能模块的应用程序模块。
  5. 一旦Google向公众发布其Android InstantApp SDK,您就可以构建Instant Apps(每个功能一个)。

4
现在Instant Apps已经面向开发者普遍可用,您可以参考官方文档。简而言之,所有Instant Apps都至少包含一个称为基础特性模块的模块,其中包含跨Instant App的通用代码。除此之外,Instant Apps还可以选择具有1个或多个附加特性库,这些特性库依赖于基础特性模块。每个特性模块都可以具有自己的入口点,可通过URL进行访问,尽管特性模块本身不需要相互依赖。如果需要调用另一个特性模块,可以通过基于URL的Intent实现。下面是文档网站上的示意图: enter image description here 所有特性模块都使用新的com.android.feature插件,其使用方式类似于传统的com.android.library插件,在Android项目中可以像使用库一样使用它,因此可以将库文档作为参考。在输出方面,与可安装的应用程序模块一起使用时,它将输出常规的AAR文件;与新的Instant App模块一起使用时,它将输出特性APK。

4
考虑以下这个图表。 enter image description here 问:如何将应用程序拆分为完全可用且 URL 可寻址的模块?
基础模块:包含应用程序所需的所有共享资源。因此,在我们的情况下,feature1 和 feature2 中的所有活动都将使用来自基本模块的共享资源。它可能具有像 dagger、butterknife 等库。
现在是时候将整个应用程序分解为称为功能的较小单元了。一个单一的功能可以由多个活动组成,这些活动可能只是给用户提供了一个关于您的应用程序的概述或完成了一个目标,从而驱使用户安装该应用程序。现在完全取决于您想要向用户传递什么东西,以便他们下载您的应用程序。
Feature1:我们已将应用程序拆分为 feature1 和 feature2。在此 feature1 中,我们让用户搜索和浏览物品。每当用户点击项目时,我们需要从 feature2 加载项目详细信息。因此,在浏览活动中单击项目时,我们将调用
Intent intent = new Intent(Intent.ACTION_VIEW,
                Uri.parse("https://yourdomain.com/itemdetail"));
        intent.setPackage(getPackageName());
        intent.addCategory(Intent.CATEGORY_BROWSABLE);
        startActivity(intent);

因为:来自feature1的Activity1不能直接调用feature2中的Activity2。要这样做,您必须从Activity1请求Activity2的URL地址。
Feature2: 现在,Feature2已加载到即时应用程序中,因此我们现在可以看到项目详细信息活动。
注意:在拆分应用程序功能时,您还应考虑功能大小,因为每个功能的大小不得超过4MB,否则上传APK到Play商店时会进行验证。

1
我不确定我是否误解了你的问题,但我会试着解答一下。在我的下面的解释中,我会多次引用Google的这个代码示例。我强烈建议克隆该repo并进行实验,因为我认为它将回答你的问题。

如果我们使用像dagger、butterknife等库,所有模块都将依赖于其他模块

如其他人所述,任何将被所有功能使用的库都将放入您的基础功能中。

如果我们的模块包含所需的(视图),则应该如何实现从另一个模块到另一个视图的转换而不导入此模块?

这个答案涵盖了概述-但这部分似乎是你问题的根源,所以我会尝试深入挖掘一下。
假设功能1(BrowseActivity)想要打开功能2(ItemDetailActivity)。 与其直接调用 startActivity(ItemDetailActivity.class),功能1将不得不使用下面的方法调用(因为它们彼此之间没有依赖关系,所以功能1无法访问功能2的ItemDetailActivity.class)。 这是Google提供的代码示例
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://example.com/itemdetail"));
intent.setPackage(getPackageName());
intent.addCategory(Intent.CATEGORY_BROWSABLE);
startActivity(intent);

现在缺失的部分是,在Feature2的AndroidManifest中,您需要声明ItemDetailActivity正在监听https://example.com/itemdetail链接。这里是来自Google的相关代码示例
<activity android:name=".ItemDetailActivity">
    <intent-filter>
      <action android:name="android.intent.action.MAIN" />
      <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    <intent-filter android:autoVerify="true">
      <action android:name="android.intent.action.VIEW" />
      <category android:name="android.intent.category.DEFAULT" />
      <category android:name="android.intent.category.BROWSABLE" />
      <data android:scheme="http" />
      <data android:scheme="https" />
      <data android:host="example.com" />
      <!-- IMPORTANT -->
      <data android:pathPrefix="/itemdetail"/>
    </intent-filter>
    <meta-data
      android:name="default-url"
      android:value="https://www.example.com/itemdetail" />
</activity>

如需获取更多信息,请查阅 数字资产链接 以及一般的 深度链接


0

我认为功能模块应该采用模块化的概念。最终,每个功能都可以分离成一个功能模块。

从这个talk开始,我开始理解新的项目结构方式。它让我清楚了一些要点。

例如,如果我们创建了一个功能模块并想要链接到功能基础模块,我们可能需要删除未使用的androidTest testres资源。

同时,在here上创建一个简单的项目。

在这个存储库上,尝试从头开始按照文档和上述步骤更改从应用程序模块到功能模块,并将即时应用程序模块添加到代码库中。


每当您链接到博客文章、库或其他外部资源(例如您的存储库)时,您必须清楚地指出这一点 - Nathan Tuggy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接