使用無頭 (headless) Oracle Content Management 在 Flutter 建立映像檔庫

簡介

Flutter 是 Google 提供的開放原始碼架構,可讓您從單一程式碼編寫建置美觀、原生編譯、多平台應用系統。Flutter 程式碼可以編譯至 ARM 或 Intel 機器碼以及 JavaScript,讓任何裝置都能得到更快速的效能。Flutter 可以是建立使用 Oracle Content Management 內容之應用系統的強大工具。隨著正確的內容模型,您可以快速建立構成典型畫廊的 Flutter UI。

本教學課程將運用 Oracle Content Management 作為無頭 (headless) CMS,在 Flutter 中建立簡單圖庫。此 Flutter 範例位於 GitHub

教學課程包含三個步驟:

  1. 準備 Oracle Content Management
  2. 建立 Flutter 中的影像圖庫
  3. 準備應用程式以進行部署

必要條件

繼續本教學課程之前,建議您先閱讀下列資訊:

若要遵循本教學課程,您需要:

我們正在打造什麼

我們的影像畫廊將由咖啡店提供幾張食品和飲料的影像組成。

此影像顯示具有不同種類的袋子的影像圖庫,有些具有奶油或上鋪,或兩者皆含。

種類是分類的下階節點,可組織成階層。對於我們的影像圖庫,不論組織為何,我們都想要顯示所有可用的類別。為了達成這目標,我們首先需要尋找能夠使用 REST API 資源 GET /published/api/v1.1/taxonomies 進行的可用分類。

接下來,我們需要為每個分類取得一組分類。您可以使用 REST API GET /published/api/v1.1/taxonomies/{id}/categories 進行這項作業。

要建立類別預覽,例如貝爾,我們需要計算前四個影像的影像數量和 URL。

此影像顯示「早餐」分類中的影像。

我們要求在類別中尋找已發布的資產,透過查詢字串指定類別條件,如下所示:

"(taxonomies.categories.nodes.id eq 892CD6BC4F654249A00CB7942EE8C773)"

備註:除了公布要檢視的數位資產之外,您也必須將分類公布至管道。

若要繼續,您必須具有 Oracle Content Management 的有效訂閱,並且以「內容管理員」角色登入。

作業 1:準備 Oracle Content Management

本教學課程以假設您已建立資產儲存庫,且目前具有空白的內容模型 (亦即,未建立任何內容類型) 為基礎。

如果您還沒有 Oracle Content Management 執行處理,請參閱快速入門以瞭解如何註冊 Oracle Cloud、佈建 Oracle Content Management 執行處理,以及將 Oracle Content Management 設為無頭 (headless) CMS。

在本教學課程中,您需要以兩種方式建立內容模型。有可下載的資產套件可供您填入含內容類型與相關內容的空白儲存庫,或者您可以建立自己的內容模型與內容。

準備 Oracle Content Management:

  1. 建立通道和資產儲存區域
  2. 匯入 Oracle Content Management Samples Asset Pack
  3. 上傳您自己的映像檔資產
  4. 建立分類標準並將他們連結至影像資產

建立通道和資產儲存區域

您必須先在 Oracle Content Management 中建立通道和資產儲存區域,才能發布內容。

在 Oracle Content Management 中建立通道與資產儲存區域:

  1. 以管理員身分登入 Oracle Content Management Web 介面。

  2. 在左側導覽功能表中選擇內容,然後從頁面標頭的選取清單中選擇發布通道

    此圖像顯示「內容」頁面標頭的下拉式功能表中選取的「發布通道」選項。

  3. 在右上角,按一下建立以建立新管道。為此教學課程的目的命名通道 'OCEImageGalleryChannel「,並讓存取權保持公開。按一下儲存以建立管道。

    此圖像顯示發佈通道定義面板,通道名稱欄位中包含 'OCEImageGalleryChannel'。

  4. 在左側導覽功能表中選擇內容,然後從頁面標頭的選取清單中選擇儲存庫

    此圖像顯示「內容」頁面標頭的下拉式功能表中選取的「儲存區域」選項。

  5. 在右上角,按一下建立以建立新的資產儲存庫。為此教學課程命名資產儲存庫 'OCEImageGalleryRepository'。

    此圖像顯示儲存庫定義面板,儲存庫名稱欄位中包含 ' OCEImageGalleryRepository'。

  6. 發佈通道欄位中,選取 OCEImageGalleryChannel 以向 Oracle Content Management 指示 OCEImageGalleryRepository 儲存區域中的內容可以發布到 OCEImageGalleryChannel 通道。完成時,按一下儲存

    此圖像顯示儲存區域定義面板,在「發布通道」欄位中顯示 」OCEImageGalleryChannel'。

匯入 Oracle Content Management Samples Asset Pack

您可以下載預先設定的 Oracle Content Management 範例資產套件,其中包含此教學課程的所有必要內容類型和資產。

您可以從 Oracle Content Management Samples Asset Pack 上傳本教學課程中所使用的內容複本。這可讓您實驗內容類型並修改內容。您可以下載資產套件封存、OCESamplesAssetPack.zip,然後將其擷取至您選擇的目錄:

  1. 從 Oracle Content Management 下載頁面下載 Oracle Content Management Samples Asset Pack (OCESamplesAssetPack.zip)。將下載的壓縮檔解壓縮到電腦上的位置。擷取之後,此位置將會包含名為 OCEImageGallery_data.zip 的檔案。

  2. 以管理員身分登入 Oracle Content Management Web 介面。

  3. 在左側導覽功能表中選擇內容,然後從頁面標頭的選取清單中選擇儲存庫。現在選取 OCEImageGalleryRepository,然後按一下頂端動作列中的匯入內容按鈕。

    此圖像顯示「儲存區域」頁面,其中已選取 OCEImageGalleryRepository 項目。

  4. 從本機電腦將 OCEImageGallery_data.zip 上傳至文件資料夾。

    此圖像顯示 OCEImageGallery_data.zip 檔案的上傳確認畫面。

  5. 上傳之後,請選取 OCEImageGallery_data.zip,然後按一下確定將內容匯入您的資產儲存庫。

    此影像顯示已選取啟用「確定」按鈕的 OCEImageGallery_data.zip 檔案。

  6. 成功匯入內容之後,請瀏覽至資產頁面並開啟 OCEImageGalleryRepository 儲存庫。您將會看到所有相關影像與內容項目現在已新增至資產儲存庫。

    此影像顯示 OCEGettingStartedRepository 儲存庫,內含剛才匯入的所有資產。

  7. 按一下左上方的全選,然後按一下發布,將所有匯入的資產新增至您先前建立的發布管道 OCEImageGalleryChannel。

    此影像顯示 OCEImageGalleryRepository 儲存庫,其中已選取所有資產,以及可看見動作列中的「發布」選項。

  8. 發布之前,您需要驗證所有資產。請先將 OCEImageGalleryChannel 新增為選取的通道,然後按一下驗證按鈕。

    此圖像顯示「驗證結果」頁面,其中「管道」欄位中新增了 OCEImageGalleryChannel 通道、要驗證的所有資產,以及啟用「驗證」按鈕。

  9. 驗證資產後,您可以按一下右上角的發布按鈕,將所有資產發布到選取的管道。

    此圖像顯示「驗證結果」頁面,其中「管道」欄位中新增了 OCEImageGalleryChannel 通道、所有已驗證的資產,以及已啟用「發布」按鈕。

完成之後,您可以在資產頁面上看到所有資產都已發布。(您可以由資產名稱上方的圖示來告知。)

此影像顯示「資產」頁面,所有資產都已暫停。

匯入 Oracle Content Management Samples Asset Pack 之後,您可以開始在 Flutter 中建立影像圖庫

上傳您自己的映像檔資產

本教學課程使用名為 'OCEImageGalleryRepository「 的資產儲存庫,為我們的藝廊網站建立首頁。此首頁包含標題「影像相簿」以及影像收藏專輯。

此圖像顯示影像畫廊的首頁,圖像種類包括三明治、飲料、甜點、早餐和食物。

將影像資產新增至圖庫資產儲存庫:

  1. 登入 Oracle Content Management Web 介面。

  2. 按一下左側導覽功能表中的資產

  3. 開啟 OCEImageGalleryRepository 儲存庫。

  4. 按一下頁面右上角的新增,將影像資產新增至圖庫資產儲存庫。

    此圖像顯示「資產」頁面,其中已開啟內容和「新增」下拉式功能表,其中顯示兩個選項:「從文件新增」和「從此電腦新增」。

  5. 從本機電腦上傳您自己的新資產,或選擇已存在於 Oracle Content Management 中的現有資產。

您必須在 Oracle Content Management 中建立分類,然後將分類指定給儲存庫中的資產。

在 Oracle Content Management 中建立分類:

  1. 以管理員身分登入 Oracle Content Management Web 介面。

  2. 在左側導覽功能表中選擇內容,然後從頁面標頭的選取清單中選擇分類

    此圖像顯示「內容」頁面標頭的下拉式功能表中選取的「分類」選項。

  3. 在右上角,按一下建立以建立新分類。為此教學課程的用途命名通道 'OCEImageGalleryTaxonomy'。

    此圖像顯示分類定義面板,分類名稱欄位中包含 'OCEImageGalleryTaxonomy'。

  4. 按一下建立

  5. 現在新增類別以建置分類。按一下新增類別

    此圖像顯示 'OCEImageGalleryTaxonomy「 分類法的「新增類別」頁面。

  6. 命名上階分類料號 'Food「,並新增下列下階分類:

    • 早餐
    • 甜點
    • 飲料
    • 桑威切斯

    按一下畫面右上方的完成

    此影像顯示分類定義頁面,其中「食物」為上階分類,這些下階分類:早餐、甜點、飲料及三明治。

  7. 在「分類標準」頁面上,選取 OCEImageGalleryTaxonomy 分類並按一下動作列中的升級,使其可用於您的資產儲存庫。

    此圖像顯示清單中選取的 OCEImageGalleryTaxonomy 分類,動作列中會顯示「提升」選項。

接著,編輯 OCEImageGalleryRepository 儲存庫以啟用該儲存庫的 OCEImageGalleryTaxonomy 分類標準:

  1. 以管理員身分登入 Oracle Content Management Web 介面。

  2. 在左側導覽功能表中選擇內容,然後從頁面標頭的選取清單中選擇儲存庫

  3. 選取並編輯 OCEImageGalleryRepository 儲存庫。

  4. 分類欄位中,選取 OCEImageGalleryTaxonomy,以便將分類從該分類指定給 OCEImageGalleryRepository 儲存庫中的資產。

    此圖像顯示儲存庫定義面板,在「分類」欄位中顯示 」OCEImageGalleryTaxonomy'。

  5. 按一下儲存

然後,將分類分類指定給 OCEImageGalleryRepository 儲存庫中的每個影像資產:

  1. 登入 Oracle Content Management Web 介面。

  2. 按一下左側導覽功能表中的資產

  3. 開啟 OCEImageGalleryRepository 儲存庫。

  4. 選取一或多個影像資產,按一下動作列中的其他,然後從功能表中選擇類別

    此圖像顯示 OCEImageGalleryRepository 儲存區域中選取的資產,其中會顯示「更多」選取功能表 (包括「類別」選項)。

  5. 在「類別」面板中,按一下新增類別。在搜尋列中搜尋類別名稱,或從分類階層結構中選取類別,然後按一下新增來指定選取的類別。您可以將多個類目指派給資產。

    此圖像顯示資產的「類別」面板,其中含有類別搜尋列與「良好」分類階層結構。

  6. 在您完成指定分類至所有影像資產之後,請選取儲存庫中的所有資產,並將其發布至 OCEImageGalleryChannel 通道。

若要在 Flutter 應用程式中使用我們的 Oracle Content Management 內容,我們可以使用 Flutter 圖庫範例,作為 GitHub 上的開放原始碼儲存區域。

注意:請記住,使用 Flutter 範例是選擇性的,我們會在本教學課程中使用它來快速開始。您也可以建置自己的 Flutter 應用程式。

在 Flutter 建立影像圖庫包含以下步驟:

  1. 安裝 Flutter
  2. 複製範例儲存區域並安裝相依性
  3. 設定 Flutter 應用程式
  4. 使用 Oracle Content Management REST API 擷取內容

安裝 Flutter

要開始使用 Flutter 的第一件事就是設定您的環境。您可以在Flutter 網站中找到設定該功能的指示。請使用與您作業系統對應的選項。以下為安裝步驟的摘要:

  1. 取得 Flutter SDK。
  2. 更新您的路徑環境變數。
  3. 執行 flutter doctor
  4. 請依照 Flutter 網站中的步驟來安裝您選擇的編輯器。
  5. 新增 Android Studio、IntelliJ、VS Code 或 Emacs 的編輯器 Plugin。指示指定如何在編輯器中安裝 Flutter 和 Dart Plugin。
  6. 修改 android.properties 檔案中的值,以參照適當的位置、sdk 和 kotlin 版本。您可能也需要修改適當版本之 android.gradle 檔案中的值。

複製範例儲存庫並安裝相依性

Flutter 圖庫範例在 GitHub 中是作為開放原始碼儲存庫。

您必須先將範例從 GitHub 複製到您的本機電腦,並將您的目錄變更到儲存庫根目錄:

git clone https://github.com/oracle-samples/oce-flutter-gallery-sample.git
cd oce-flutter-gallery-sample

從 Android Studio 或您選擇的任何其他編輯器開啟專案。若要取得專案中使用的所有套裝軟體,請按一下 [取得套裝軟體] 按鈕。

設定 Flutter 應用程式

在此 Flutter 藝廊範例中,您必須設定一些資訊,讓您的 REST API 要求能夠以正確的通道權杖作為正確的執行處理 URL 和 API 版本目標。lib/config/oce.dart 中定義的這些值會由 lib/networking/content.dart 中定義的函數使用,以建立 REST API 的端點。

您可以在 lib/config/oce.dart 中看到下列資訊:

const Map<String, String> config = <String, String>{
  'serverUrl': 'https://samples.mycontentdemo.com',
  'apiVersion': 'v1.1',
  'channelToken': 'e0b6421e73454818948de7b1eaddb091'
};

變更每個索引鍵 - 值組以反映您的執行處理 URL、要目標的 API 版本,以及與您的發布通道關聯的通道權杖。本教學課程的管道為 OCEImageGalleryChannel。

使用 Oracle Content Management REST API 擷取內容

內容傳遞的 REST API 提供存取 Oracle Content Management 中發布的資產。發布的資產包括內容項目與數位資產,以及其轉譯。現在,我們可以運用 Oracle Content Management REST API 擷取內容,以便在我們的映像檔庫 Flutter 應用程式中轉譯內容。

lib/networking/content.dart 檔案具有使用 REST API 連線至 oce.dart 檔案中所指定伺服器的方法,並傳回其回應。

  //Utility method to build up the URL for published content.
  String _getPublishedContentServerURL() {
    final String? serverUrl = data['serverUrl'] as String?;
    final String? apiVersion = data['apiVersion'] as String?;
    return '$serverUrl/content/published/api/$apiVersion/';
  }

  // Adds the channel token to the URL
  String _addChannelToURL(String currUrl) {
    final String? channelToken = data['channelToken'] as String?;
    return '$currUrl?channelToken=$channelToken';
  }

  //Make an http get call and return the response if successful
  Future<dynamic> _get(String url) async {
    dynamic responseJson;
    try {
      final Response response = await get(Uri.parse(url));
      responseJson = _returnResponse(response);
    } on SocketException {
      throw FetchDataException(kConnectionError);
    }
    return responseJson;
  }

  //Return the json decoded response body if response status is successful
  dynamic _returnResponse(Response response) {
    switch (response.statusCode) {
      case 200:
        final Map<String, dynamic>? responseJson =
            json.decode(response.body.toString()) as Map<String, dynamic>?;
        return responseJson;
      case 400:
        throw BadRequestException(response.body.toString());
      case 401:
      case 403:
        throw UnauthorizedException(response.body.toString());
      case 500:
      default:
        throw FetchDataException('StatusCode : ${response.statusCode}');
    }
  }

為轉譯影像,content.dart 也提供輔助方法來擷取資產的各種轉譯。

  String getMediumRenditionUrl(Map<String, String> args) {
    final String itemId = args['id'];
    if (itemId == null) return null;
    String url = _getPublishedContentServerURL();
    url = '${url}assets/$itemId/Medium';
    // add the channel token to the URL
    url = _addChannelToURL(url);
    url = '$url&format=jpg&&type=responsiveimage';
    return url;
  }

  String getRenditionURL(Map<String, String> args) {
    final String itemId = args['id'];
    if (itemId == null) return null;
    String url = _getPublishedContentServerURL();
    url = '${url}assets/$itemId/native';
    // add the channel token to the URL
    url = _addChannelToURL(url);
    return url;
  }

lib/networking/services.dart 檔案包含用於取得應用程式資料的所有程式碼。

首頁資料

首頁需要數次資料呼叫來取得其所有資料:

  1. 首先,我們載入 oce.dart 中指定之通道的分類。
  2. 針對每個分類,我們會取得該分類中的所有分類。
  3. 針對每個類別,我們會在該類別中取得四個內容項目。
  4. 針對每個項目,我們擷取其轉譯 URL。

開啟 lib/networking/services.dart 並尋找下列函數,可協助取得首頁的所有資料。

fetchTaxonomies() 與 fetchCategories() 函數結合,可獲得所有分類中的所有分類。接著會呼叫 fetchItemsForCategory 函數,將四個類別項目新增至每個類別。最後會呼叫 retrieveThumbnailURL 以取得縮圖 URL。

  // Fetch the taxonomies for the channel
  Future<List<String>> fetchTaxonomies() async {
    final Content content = Content();
    try {
      dynamic data = await content.getTaxonomies();
      dynamic taxonomies = data['items'];
      List<String> idArray = [];
      for (var taxonomy in taxonomies) {
        idArray.add(taxonomy['id']);
      }
      return idArray;
    } catch (exception) {
      rethrow;
    }
  }

  // Fetch the categories for the specified taxonomyId.
  Future<List<dynamic>> fetchCategories(taxonomyId) async {
    final Content content = Content();
    dynamic data = await content.queryTaxonomyCategories({
      'id': '$taxonomyId',
    });
    return data['items'];
  }

  // Fetch the items that belong to the specified category
  Future<dynamic> fetchItemsForCategory(String categoryId, bool limit) async {
    final Content content = Content();
    dynamic data = await content.queryItems({
      'q': '(taxonomies.categories.nodes.id eq "$categoryId")',
      'fields': 'all',
      'expand': 'all',
      'limit': limit ? '4' : '100',
      'totalResults': 'true',
    });
    return data;
  }

  // Retrieve the thumbnail URL for the item specified.
  Future<String> retrieveThumbnailURL(identifier) async {
    final Content content = Content();
    dynamic data = await content.getItem({
      'id': identifier,
      'fields': 'all',
      'expand': 'all',
    });
    String url = data['fields']['renditions'][1]['formats'][0]['links'][0]['href'];
    return url;
  }

影像方格頁面

影像方格頁面會接收種類 ID,且需要數個資料呼叫來取得其所有資料:

  1. 取得指定類別的所有項目。
  2. 為每個項目取得其轉譯 URL。

開啟 lib/networking/services.dart 並尋找下列函數,由 image_grid.dart 中的 fetchData 函數使用。

  Future<dynamic> fetchItemsForCategory(String categoryId, bool limit) async {
    final Content content = Content();
    dynamic data = await content.queryItems({
      'q': '(taxonomies.categories.nodes.id eq "$categoryId")',
      'fields': 'all',
      'expand': 'all',
      'limit': limit ? '4' : '100',
      'totalResults': 'true',
    });
    return data;
  }

它會呼叫 fetchItemsForCategory,如首頁一樣,但沒有限制,因此傳回所有項目,而不是只傳回 4 個。

現在我們有資料查詢,我們可以在 Flutter 元件中呈現回應。

Flutter 元件

圖庫應用程式會將每個頁面細分為數個較小的元件。

以下幾節提供 Flutter 在每個元件中如何轉譯應用程式的簡介:

HomePage 元件

首頁包含分類分類的分類清單,預覽該分類中的四個項目。它是由位於 lib/screens/home_page.dart 的 HomePage 元件所轉譯。元件使用 services.dart 檔案中所定義的函數來取得資料。

  Future<void> fetchData() async {
    final Services services = Services();
    try {
      List<String> taxonomyIdArray = await services.fetchTaxonomies();
      // For each taxonomy, fetch the categories and append them to an array
      for (var taxonomyId in taxonomyIdArray) {
        List<dynamic> data = await services.fetchCategories(taxonomyId);
        for (var categoryData in data) {
          categories.add(CategoryListItemModel.fromJson(categoryData));
        }
        setState(() {
          categories = categories;
        });
      }
    } catch (exception) {
      setState(() => this.exception = exception.toString());
      print(exception.toString());
    }
  }

此檔案也使用位於 lib/components/card_grid.dart 的元件來繪製網格中的影像。

ImageGrid 元件

ImageGridPage 元件會顯示類別中的項目。它是由 ImageGrid 元件 (位於 lib/screens/image_grid.dart) 所轉譯。

元件會呼叫以從 services.dart 檔案取得資料。

  Future<void> fetchData() async {
    final Services services = Services();

    String categoryId = widget.category.id;
    try {
      dynamic categoryItems =
          await services.fetchItemsForCategory(categoryId, false);
      items = categoryItems['items'];
      setState(() {
        dataFetched = true;
      });
    } catch (exception) {
      setState(() {
        this.exception = exception.toString();
      });
      print(exception.toString());
    }
  }

ImagePager 元件

位於 lib/screens/image_pager.dart 的 ImagePager 元件會以滑動呼叫器表單顯示項目。

作業 3:準備應用程式以進行部署

我們已建置 Flutter 映像檔庫網站,因此需要將它部署在模擬器或裝置上,以便在正式上線前對應用程式進行除錯。

請依照 Flutter 網站中的指示,讓編輯器執行應用程式。

  1. 如果您使用 Android Studio 作為編輯器,請尋找主要的 Android Studio 工具列。
  2. 在目標選取器中,選取要執行應用程式的 Android 裝置。如果沒有列出可用的話,請選取「工具 > Android > AVD 管理員」,然後在該處建立一個。如需詳細資訊,請參閱管理 AVD
  3. 按一下工具列中的執行圖示,或者呼叫功能表項目「執行 (Run)」>「執行 (Run)」。

結論

本教學課程將引導您在 GitHub 中尋找 Flutter 語系網站。此網站使用 Oracle Content Management 作為無頭 (headless) CMS。在設定和設定 Oracle Content Management 的藝廊網站教學課程已發布內容通道之後,我們就會安裝並執行 Flutter 網站來擷取必要內容並建立網站。

如需有關 Flutter 的詳細資訊,請前往 Flutter 網站

瞭解文件中的重要 Oracle Content Management 概念。

您可以在 Oracle Help CenterOracle Content Management Samples 頁面找到更多範例。