使用无头 Oracle Content Management 构建适用于 Android 的博客应用

简介

使用 Java 或 Kotlin 的 Android 开发环境可以成为构建使用 Oracle Content Management 内容的应用程序的一个强大工具。借助合适的内容模型,您可以快速构建构成典型博客应用程序的 Android 用户界面。

在本教程中,我们将利用 Oracle Content Management 作为无头 CMS,为 Android 构建一个简单的博客应用程序。此 Android 示例可在 GitHub 上找到。

本教程包含三个步骤:

  1. 准备 Oracle Content Management
  2. 在 Android 中构建博客
  3. 为应用程序做好部署准备

先决条件

在继续本教程之前,我们建议您首先阅读以下信息:

要遵循本教程,您需要:

我们正在构建什么

我们的博客应用程序包含三个屏幕,允许访问者浏览按主题组织的博客文章。第一个屏幕(主屏幕)将包含博客主题的列表。

要了解我们正在构建的内容,本教程的终结状态是使用 Oracle Content Management 内容的基本 Android 博客应用程序。

以下是本教程末尾的主屏幕

此图显示 Cafe Supremo 演示站点的主屏幕,其中包含可用主题的列表。

第二页(主题屏幕)显示属于某个主题的每个博客文章的预览。下面是单个主题屏幕的外观:

此图显示一个名为“如何制造咖啡”的主题屏幕,其中包含该主题的可用文章列表。

最后,文章屏幕会呈现最终的博客文章,包括有关博客作者的信息。以下是单个文章页面的外观:

此图显示单个文章页,其中包含内容和作者参考。

要继续,您需要主动订阅 Oracle Content Management 并使用内容管理员角色登录。

任务 1:准备 Oracle Content Management

如果您还没有 Oracle Content Management 实例,请参阅快速入门以了解如何注册 Oracle Cloud、预配 Oracle Content Management 实例以及将 Oracle Content Management 配置为无头 CMS。

在本教程中,您需要通过两种方式之一创建内容模型。有一个可下载的资产包可用,该包将填充空资料档案库中的内容类型和关联内容,您也可以创建自己的内容模型和内容。

要准备 Oracle Content Management,请执行以下操作:

  1. 创建通道和资产资料档案库
  2. 使用以下两种方法之一创建内容模型

创建通道和资产资料档案库

您首先需要在 Oracle Content Management 中创建通道和资产资料档案库,以便可以发布内容。

要在 Oracle Content Management 中创建通道和资产资料档案库,请执行以下操作:

  1. 作为管理员登录 Oracle Content Management Web 界面。

  2. 在左侧导航菜单中选择内容,然后从页眉的选择列表中选择发布渠道

    此图显示在“内容”页标题的下拉菜单中选择的“发布渠道”选项。

  3. 在右上角,单击创建以创建新通道。为此教程命名通道 ‘ OCEGettingStartedChannel ’,并保持公开访问。单击保存以创建通道。

    此图显示发布通道定义面板,通道名称字段中包含 'OCEGettingStartedChannel'。

  4. 在左侧导航菜单中选择内容,然后从页眉的选择列表中选择资料档案库

    此图显示在“内容”页标题的下拉菜单中选择的“资料档案库”选项。

  5. 在右上角,单击创建以创建新的资产存储库。为此教程将资产资料档案库命名为 'OCEGettingStartedRepository'。

    此图显示系统信息库定义面板,系统信息库名称字段中包含 "OCEGettingStartedRepository"。

  6. 发布渠道字段中,选择 OCEGettingStartedChannel 通道以向 Oracle Content Management 表明 OCEGettingStartedRepository 资料档案库中的内容可以发布到 OCEGettingStartedChannel 通道。完成后,单击保存

    此图显示存储库定义面板,在“发布渠道”字段中显示 ”OCEGettingStartedChannel”。

创建内容模型

下一步是创建内容模型。您可以使用以下两种方法之一:

导入 Oracle Content Management 示例资产包

您可以下载预配置的 Oracle Content Management 示例资产包,其中包含此教程的所有必需内容类型和资产。如果您愿意,还可以创建自己的内容模型,而不是下载示例资产包。

您可以从 Oracle Content Management 示例资产包上载在本教程中使用的内容的副本。这将允许您试验内容类型并修改内容。如果要导入 Oracle Content Management 示例资产包,请下载资产包档案 OCESamplesAssetPack.zip,并将其提取到您选择的目录中:

  1. 从 Oracle Content Management 下载页下载 Oracle Content Management 示例资产包 (OCESamplesAssetPack.zip)。将下载的 zip 文件解压缩到计算机上的某个位置。提取之后,此位置将包含一个名为 OCEGettingStarted_data.zip 的文件。

  2. 作为管理员登录 Oracle Content Management Web 界面。

  3. 在左侧导航菜单中选择内容,然后从页眉的选择列表中选择资料档案库。现在选择 OCEGettingStartedRepository ,然后单击顶部操作栏中的导入内容按钮。

    此图显示“资料档案库”页,其中选择了 OCEGettingStartedRepository 项。

  4. 将 OCEGettingStarted_data.zip 从本地计算机上载到文档文件夹。

    此图显示 OCEGettingStarted_data.zip 文件的上载确认屏幕。

  5. 上载后,选择 OCEGettingStarted_data.zip ,然后单击确定将内容导入到资产存储库中。

    此图显示已启用“确定”按钮的选定 OCEGettingStarted_data.zip 文件。

  6. 成功导入内容后,导航到资产页并打开 OCEGettingStartedRepository 系统信息库。您将看到所有相关图像和内容项现已添加到资产存储库中。

    此图显示 OCEGettingStartedRepository 资料档案库,其中包含刚导入的所有资产。

  7. 单击左上方的全选,然后单击发布以将所有导入的资产添加到之前创建的发布渠道 OCEGettingStartedChannel。

    此图显示 OCEGettingStartedRepository 资料档案库,其中选择了所有资产,操作栏中的“发布”选项可见。

  8. 在发布之前,您需要验证所有资产。首先将 OCEGettingStartedChannel 添加为所选通道,然后单击验证按钮。

    此图显示“验证结果”页,并在“渠道”字段中添加了 OCEGettingStartedChannel 渠道、要验证的所有资产以及“验证”按钮。

  9. 验证资产后,可以通过单击右上角的发布按钮将所有资产发布到选定的渠道。

    此图显示“验证结果”页,其中在“渠道”字段中添加了 OCEGettingStartedChannel 渠道,验证了所有资产,并启用了“发布”按钮。

完成此操作后,您可以在资产页面上看到所有资产都已发布。(可以通过资产名称上方的图标来确定。)

此图显示“资产”页,其中已发布所有资产。

导入 Oracle Content Management 示例资产包后,您可以开始在 Android 中构建博客

创建您自己的内容模型

您还可以创建自己的内容模型,而不是导入 Oracle Content Management 示例资产包

在本教程中,我们使用名为“OCEGettingStartedHomePage”的内容类型来构建博客的主屏幕。此主页包含应包含在屏幕上的博客主题列表。

此图显示了 Cafe Supremo 演示站点的主屏幕。

要为内容模型创建内容类型,请执行以下操作:

  1. 作为管理员登录 Oracle Content Management Web 界面。
  2. 在左侧导航菜单中选择内容,然后从页眉的选择列表中选择资产类型
  3. 单击右上角的创建
  4. 选择创建内容类型(不是数字资产类型)。对所有必需的内容类型重复此操作。

此图显示 Oracle Content Management Web 界面中的“创建资产类型”对话框。

我们将创建四种内容类型,每种类型都有自己的一组字段:

第一个内容类型 OCEGettingStartedHomePage 应具有以下字段:

显示名称 字段类型 要求 计算机名
公司名称 单值文本字段 X company_name
公司标识 单值文本字段 X company_logo
主题 多值参考字段 X 主题
联系人 URL 单值文本字段 X contact_url
关于 URL 单值文本字段 X about_url

OCEGettingStartedHomePage 内容类型定义应如下所示:

此图显示内容类型“OCEGettingStartedHomePage”的定义。它包括以下数据字段:“公司名称”、“公司标识”、“主题”、“联系人 URL”和“关于 URL”。

第二种内容类型 OCEGettingStartedTopic 应具有以下字段:

显示名称 字段类型 要求 计算机名
缩略图 单值图像字段 X 缩略图

OCEGettingStartedTopic 内容类型应如下所示:

此图显示内容类型“OCEGettingStartedTopic”的定义。它包括此数据字段:缩略图。

第三种内容类型 OCEGettingStartedAuthor 应具有以下字段:

显示名称 字段类型 要求 计算机名
头像 单值图像字段 X 头像

OCEGettingStartedAuthor 内容类型应如下所示:

此图显示内容类型“OCEGettingStartedAuthor”的定义。它包括此数据字段:头像。

第四个和最后一个内容类型 OCEGettingStartedArticle 应具有以下字段:

显示名称 字段类型 要求 计算机名
发布日期 单值日期字段 X published_name
作者 单值引用字段 X 作者
图像 单值图像字段 X 图像
图像标题 单值文本字段 X image_caption
文章内容 单值大文本字段 X article_content
主题 单值引用字段 X 主题

OCEGettingStartedArticle 内容类型应如下所示:

此图显示内容类型“OCEGettingStartedArticlePage”的定义。它包括以下数据字段:“发布日期”、“作者”、“图像”、“图像标题”、“文章内容”和“主题”。

创建内容类型后,您可以将这些内容类型添加到之前创建的资料档案库 OCEGettingStartedRepository:

  1. 作为管理员登录 Oracle Content Management Web 界面。
  2. 导航到 OCEGettingStartedRepository
  3. 编辑资料档案库,然后在资产类型下指定所有四个新创建的内容类型。单击 Save 按钮以保存更改。

此图显示 Oracle Content Management 中的“编辑资料档案库”页,其中包含与 OCEGettingStartedRepository 资料档案库关联的四个新创建的内容类型。

将内容类型添加到资料档案库后,可以在资产页上打开 OCEGettingStartedRepository 资料档案库,并开始为所有内容类型创建内容项。

此图显示 Oracle Content Management Web 界面的“资产”页上的内容项,左侧包含集合、渠道、语言、类型、内容项选择和状态选项。

任务 2:在 Android 中构建博客应用程序

为了在 Android 应用程序中使用我们的 Oracle Content Management 内容,我们可以使用 Kotlin 中编写的 Android 博客示例,该示例在 GitHub 上作为开源资料档案库提供。

注意:请记住,使用 Android 示例是可选的,在本教程中使用它可帮助您快速入门。您还可以在 Java 或 Kotlin 中构建自己的 Android 应用,因为这两种应用都与 SDK 兼容。

在 Android 中构建博客包括以下步骤:

  1. 克隆示例存储库和 Android SDK,并在本地发布 SDK
  2. 配置 Android 应用程序
  3. 使用 Oracle Content Management REST API 提取内容

克隆示例资料档案库和 Android SDK,并在本地发布 SDK

Android 博客样例可作为 GitHub 上的开源系统信息库提供。

如果尚未将示例从 GitHub 克隆到本地计算机以及 Android SDK,则需要先从 GitHub 克隆。

一旦您有了示例代码和 SDK,为了在示例项目中使用 Android SDK,您应在本地 Maven 资料档案库中构建并发布 SDK,以便示例项目可以使用该 SDK。在 Android Studio 中打开 Android SDK 项目并运行 publishToMavenLocal 任务,以构建 SDK 并将其发布到本地 Maven 资料档案库。

在 Android Studio 中打开 Android 示例

与任何 Android 应用程序一样,你需要将其导入 Android Studio,这样你可以在 Android 仿真器或设备中构建和运行它。示例代码已预先配置了用于获取博客应用程序数据的服务器和发布通道。

使用 Oracle Content Management REST API 提取内容

通过 REST API for Content Delivery ,可以访问 Oracle Content Management 中发布的资产。发布的资产包括内容项和数字资产以及其重现。现在,我们可以使用 REST API for Content Management 提取内容,以便可以在博客应用程序中呈现内容。

src/.../samples/blog/MainActivity.kt 文件具有用于创建 ContentDeliveryClient 对象的函数,该对象用于调用 REST API。以下函数是样例应用程序中函数的简化版本,显示正在使用的值。

   fun createDeliveryClient() {

        // preferences for cache
        val cacheEnabled = true

        // the server url and channel token for blog data
        val serverUrl = "https://ocemobile-oce0002.cec.ocp.oraclecloud.com"
        val channelToken = "b9ea60be0abf7255934cd2202fcf1314"


        val settings = ContentSettings()
        if (cacheEnabled) {
            // enable caches, using default settings
            settings.enableCache(appContext.cacheDir)
        }

        // SDK: create client API we'll use to make calls
        deliveryClient =
                ContentSDK.createDeliveryClient(
                        serverUrl,
                        channelToken,
                        settings)
    }

用于获取数据以填充博客示例应用程序的核心类位于“viewmodel”程序包下,后缀为“Repository”。例如,文件 HomePageRepository.kt 包含用于获取博客应用程序主页数据的方法,包括主页上显示的主题列表。

主页数据

主页需要多次数据调用才能获取其所有数据:

  1. 首先,我们查询渠道中与主页类型匹配的项。
  2. 然后提取每个主题项的详细信息。

下面是使用 SDK 提取主页数据的函数。此函数显示使用的值,而示例应用程序函数使用常量。

  private fun getHomePage(): HomePage {

        // SDK: create search request to get home page
        val getHomePageRequest = SearchAssetsRequest(ContentApi.deliveryClient)
                .type("OCEGettingStartedHomePage")    // search by content type
                .name("HomePage")    // ...and by content name
                .linksNone()        // do not include links in the response
                .fieldsAll()        // do include all fields

        val searchResult = getHomePageRequest.fetchResult()

        // from the search result, only expect a single home page
        val contentItems = searchResult.contentItems

        // handle situation where no data is returned
        if (contentItems.isNullOrEmpty())
            throw ContentException(ContentException.REASON.itemNotFound, "No home page found for type")

        // get first itme in home page data
        val item = contentItems.first()

        // convert list of ids into topic list
        val topicList = item.getReferenceListIds("topics").map { Topic(it) }
        // grab the topic type from one of the references
        topicType = item.getReferenceListField("topics").first().value.type

        return HomePage(
                companyName = item.getTextField("company_name"),
                logoImageUrl = item.getDigitalAssetField("company_logo").getThumbnailUrl(),
                contactUrl = item.getTextField("contact_url"),
                aboutUrl = item.getTextField("about_url"),
                topics = topicList.associateBy { it.id }) // convert list to map

    }

上述代码中的 SearchAssetsRequest 对象将创建请求,fetchResult() 函数将执行类似于以下请求的同步 REST 调用来获取主页数据。

GET content/published/api/v1.1/items?q=(type eq "OCEGettingStartedHomePage" AND name eq "HomePage")?fields=all&links=none&channelToken={channelToken}

主题页

“文章”屏幕显示给定主题的所有文章。我们使用与主页相同的模式,但这次搜索引用主题 ID 为已选择的主题的 OCEGettingStartedArticle 类型的内容项。这还说明了如何使用 SDK 进行异步方法调用。有关更多详细信息,请参见文件 ArticlesRepository.kt,但以下是显示所用模式和值的核心方法。

// SDK: create search request to get all the articles
// sort by published_date field in descending order
   
val searchRequest = SearchAssetsRequest(ContentApi.deliveryClient)
        .type("OCEGettingStartedArticle")                // get "article" type
        .fieldEquals("topic", topicId)  // match topic id (e.g. drinks, recipes)
        .sortByField("published_date")  // sort by published date (optional)
        .sortOrderDescending(true)
        .linksNone()            // no need for links (optional)

// SDK: make request to get articles using async callback method
   
searchRequest.fetchAsync {response ->
     // successful SDK call?
     if (response.isSuccess) {
         // process the list and display in ui
      } else {
         // handle error case
      }
  }   
  

文章页面

单个文章屏幕显示单个文章,但屏幕包含来自作者的内容,这是一个单独的内容类型。要提取一个内容项及其引用的任何内容项,请在创建请求对象时使用 ext() 方法,如下所示获取 fields.author。详细信息采用 AritcleDetailRepository.kt,但以下是核心代码模式:

// make a call to get the article, expanding the "author" field

val request  = GetContentItemRequest(ContentApi.deliveryClient, articleId)
       .expand("author")     // only expand the author field
       .linksNone()

// get the article detail as an asynchronous call

request.fetchAsync {response ->
     // successful SDK call?
     if (response.isSuccess) {
         // process the list and display in ui
      } else {
         // handle error case
      }
  }   

现在我们有了数据查询,我们可以在 Android 应用 UI 中呈现响应。

Android ViewModel 类

博客应用程序结构化为标准的 ViewModel Android 应用程序。有许多在线资源描述 ViewModel 如何在 Android 中使用并在 Kotlin 实现。

组件结构

应用程序中的每个屏幕有三个核心类:

例如,文章列表屏幕中的类包括:

任务 3:准备应用程序以进行部署

现在我们已经构建了 Android 博客应用程序,我们需要在 Android Studio 的移动仿真器或设备中测试它,这样我们就可以调试任何问题,并在应用程序上线之前预览应用程序。

总结

在本教程中,我们创建了一个适用于 Android 的博客应用程序,可在 GitHub 上找到该应用程序。此网站使用 Oracle Content Management 作为无头 CMS。在为博客网站教程设置和配置 Oracle Content Management 后,我们安装并运行 Android 站点来获取所需内容并构建站点。

通过文档了解重要的 Oracle Content Management 概念。

您可以在 Oracle 帮助中心的 Oracle Content Management 示例页上找到更多类似这样的示例。