Google is committed to advancing racial equity for Black communities. See how.
本頁面由 Cloud Translation API 翻譯而成。
Switch to English

Firebase的雲功能

在此代碼實驗室中,您將學習如何使用Firebase SDK for Google Cloud Functions來改進聊天Web應用程序,以及如何使用Cloud Functions將通知發送給聊天應用程序用戶。

3b1284f5144b54f6.png

你會學到什麼

  • 使用Firebase SDK創建Google Cloud Functions。
  • 根據Auth,Cloud Storage和Cloud Firestore事件觸發Cloud Functions。
  • 將Firebase Cloud Messaging支持添加到您的Web應用程序。

你需要什麼

  • 您選擇的IDE /文本編輯器,例如WebStormAtomSublime
  • 安裝了NodeJS v8的運行Shell命令的終端。
  • 瀏覽器,例如Chrome。
  • 示例代碼。請參閱下一步。

從命令行克隆GitHub存儲庫

git clone https://github.com/firebase/friendlychat

導入入門應用

使用您的IDE,打開或導入android_studio_folder.png示例代碼目錄中的cloud-functions-start目錄。該目錄包含代碼實驗室的起始代碼,該代碼實驗室由功能全面的Chat Web App組成。

建立專案

Firebase控制台中,單擊“添加項目”,並將其命名為FriendlyChat

單擊創建項目

啟用Google身份驗證

為了讓用戶登錄該應用,我們將使用需要啟用的Google身份驗證。

在Firebase控制台中,打開“開發”部分>“身份驗證” >“登錄方法”標籤(或單擊此處轉到此處),您需要啟用Google登錄提供程序,然後單擊“保存” 。這將允許用戶使用其Google帳戶登錄Web應用。

也可以隨時將您應用的公開名稱設置為“友好聊天”

8290061806aacb46.png

啟用雲存儲

該應用程序使用Cloud Storage上傳圖片。要在Firebase項目上啟用Cloud Storage,請訪問“存儲”部分,然後單擊“入門”按鈕。當您收到有關安全規則的免責聲明時,請單擊“得到它”

842ad84821323ef5.png

Firebase命令行界面(CLI)允許您在本地提供Web應用程序並部署Web應用程序和Cloud Functions。

要安裝或升級CLI,請運行以下npm命令:

npm -g install firebase-tools

要驗證CLI是否已正確安裝,請打開控制台並運行:

firebase --version

確保Firebase CLI的版本高於4.0.0 ,以使其具有Cloud Functions所需的所有最新功能。如果沒有,請運行npm install -g firebase-tools進行升級,如上所示。

通過運行以下命令授權Firebase CLI:

firebase login

確保您位於cloud-functions-start目錄中,然後將Firebase CLI設置為使用Firebase項目:

firebase use --add

然後選擇您的項目ID,然後按照說明進行操作。出現提示時,您可以選擇任何別名,例如codelab

現在,您已經導入並配置了項目,就可以開始運行Web應用程序了。在cloud-functions-start文件夾中打開一個控制台,然後運行firebase deploy --except functions這只會將Web應用程序部署到Firebase託管:

firebase deploy --except functions

這是您應該看到的控制台輸出:

i deploying database, storage, hosting
✔  database: rules ready to deploy.
i  storage: checking rules for compilation errors...
✔  storage: rules file compiled successfully
i  hosting: preparing ./ directory for upload...
✔  hosting: ./ folder uploaded successfully
✔ storage: rules file compiled successfully
✔ hosting: 8 files uploaded successfully
i starting release process (may take several minutes)...

✔ Deploy complete!

Project Console: https://console.firebase.google.com/project/friendlychat-1234/overview
Hosting URL: https://friendlychat-1234.firebaseapp.com

開啟網路應用程式

最後一行應顯示託管URL。現在應從該URL提供Web應用程序,該URL的形式應為https:// <project-id> .firebaseapp.com。打開它。您應該看到聊天應用程序的功能UI。

使用“用GOOGLE登錄”按鈕登錄該應用,並隨時添加一些消息和發布圖片:

3b1284f5144b54f6.png

如果您是第一次使用新的瀏覽器登錄該應用,請確保在出現提示時允許通知: 8b9d0c66dc36153d.png

我們需要您稍後啟用通知。

如果您不小心單擊了阻止,則可以通過以下方法更改此設置:單擊Chrome Omnibar中URL左側的🔒安全按鈕,然後選擇“通知”>“始終在此站點上允許”

e926868b0546ed71.png

現在,我們將使用Firebase SDK for Cloud Functions添加一些功能。

雲功能使您可以輕鬆地在雲中運行代碼,而無需設置服務器。我們將向您展示如何構建對Firebase Auth,Cloud Storage和Firebase Realtime Database事件做出反應的功能。讓我們從Auth開始。

在將Firebase SDK用於Cloud Functions時,您的Functions代碼將位於functions目錄下(默認情況下)。您的Functions代碼也是Node.js應用程序,因此需要package.json來提供有關您的應用程序的一些信息並列出依賴項。

為了使您更輕鬆,我們已經創建了functions/index.js文件,您可以在該文件中找到代碼。在繼續前進之前,請隨時檢查此文件。

cd functions
ls

如果您不熟悉Node.js ,它將有助於在繼續進行代碼實驗室之前進一步了解它。

package.json文件已經列出了兩個必需的依賴項:用於Cloud FunctionsFirebase SDKFirebase Admin SDK 。要在本地安裝它們, npm installfunctions文件夾運行npm install

npm install

現在讓我們看一下index.js文件:

index.js

/**
 * Copyright 2017 Google Inc. All Rights Reserved.
 * ...
 */

// TODO(DEVELOPER): Import the Cloud Functions for Firebase and the Firebase Admin modules here.

// TODO(DEVELOPER): Write the addWelcomeMessage Function here.

// TODO(DEVELOPER): Write the blurImages Function here.

// TODO(DEVELOPER): Write the sendNotification Function here.

我們將首先導入所需的模塊,然後編寫三個Function代替TODO。首先,讓我們導入所需的Node模塊。

在此代碼實驗室期間,將需要兩個模塊, firebase-functions模塊允許我們編寫Cloud Functions觸發規則,而firebase-admin模塊允許我們在具有管理員訪問權限的服務器上使用Firebase平台,例如寫入Cloud Firestore或發送FCM通知。

index.js文件中,將以下第一個TODO替換為:

index.js

/**
 * Copyright 2017 Google Inc. All Rights Reserved.
 * ...
 */

// Import the Firebase SDK for Google Cloud Functions.
const functions = require('firebase-functions');
// Import and initialize the Firebase Admin SDK.
const admin = require('firebase-admin');
admin.initializeApp();

// TODO(DEVELOPER): Write the addWelcomeMessage Function here.

// TODO(DEVELOPER): Write the blurImages Function here.

// TODO(DEVELOPER): Write the sendNotification Function here.

當部署在Cloud Functions環境或其他Google Cloud Platform容器上時,可以自動配置Firebase Admin SDK。這是我們在調用admin.initializeApp();admin.initializeApp();

現在,讓我們添加一個功能,該功能在用戶首次登錄您的聊天應用程序時運行,並且我們將添加一個聊天消息來歡迎用戶。

聊天消息結構

發佈到FriendlyChat聊天供稿的消息存儲在Cloud Firestore中。讓我們看一下用於消息的數據結構。為此,將新消息發佈到聊天室中,並顯示“ Hello World”:

11f5a676fbb1a69a.png

它應顯示為:

fe6d1c020d0744cf.png

在Firebase應用程序控制台中,單擊“開發”部分下的“數據庫”。您應該看到消息集合和一個包含所寫消息的文檔:

442c9c10b5e2b245.png

如您所見,聊天消息作為文檔存儲在Cloud Firestore中, nameprofilePicUrltexttimestamp屬性添加到了messages集合中。

添加歡迎信息

第一個Cloud Function添加一條消息,歡迎新用戶加入聊天。為此,我們可以使用觸發器functions.auth().onCreate ,該觸發器在用戶每次首次登錄Firebase應用程序時運行該函數。將addWelcomeMessages函數添加到index.js文件中:

index.js

// Adds a message that welcomes new users into the chat.
exports.addWelcomeMessages = functions.auth.user().onCreate(async (user) => {
  console.log('A new user signed in for the first time.');
  const fullName = user.displayName || 'Anonymous';

  // Saves the new welcome message into the database
  // which then displays it in the FriendlyChat clients.
  await admin.firestore().collection('messages').add({
    name: 'Firebase Bot',
    profilePicUrl: '/images/firebase-logo.png', // Firebase logo
    text: `${fullName} signed in for the first time! Welcome!`,
    timestamp: admin.firestore.FieldValue.serverTimestamp(),
  });
  console.log('Welcome message written to database.');
});

將此功能添加到特殊exports像是Node使該功能可在當前文件之外訪問的方式,並且對於Cloud Functions是必需的。

在上面的功能中,我們將“ Firebase Bot”發布的新歡迎消息添加到聊天消息列表中。我們通過在Cloud Firestore中的messages集合上使用add方法來執行此操作,該方法是存儲聊天消息的位置。

由於這是異步操作,因此我們需要返回Promise,以指示Cloud Firestore寫入何時完成,以便Functions不會過早退出執行。

部署功能

該功能僅在部署後才處於活動狀態。在命令行上運行firebase deploy --only functions

firebase deploy --only functions

這是您應該看到的控制台輸出:

i  deploying functions
i  functions: ensuring necessary APIs are enabled...
⚠  functions: missing necessary APIs. Enabling now...
i  env: ensuring necessary APIs are enabled...
⚠  env: missing necessary APIs. Enabling now...
i  functions: waiting for APIs to activate...
i  env: waiting for APIs to activate...
✔  env: all necessary APIs are enabled
✔  functions: all necessary APIs are enabled
i  functions: preparing functions directory for uploading...
i  functions: packaged functions (X.XX KB) for uploading
✔  functions: functions folder uploaded successfully
i  starting release process (may take several minutes)...
i  functions: creating function addWelcomeMessages...
✔  functions[addWelcomeMessages]: Successful create operation. 
✔  functions: all functions deployed successfully!

✔  Deploy complete!

Project Console: https://console.firebase.google.com/project/friendlypchat-1234/overview

測試功能

功能成功部署後,您將需要有一個首次登錄的用戶。

  1. 使用託管URL(以https://<project-id>.firebaseapp.com的形式)在瀏覽器中打開您的應用程序。
  2. 對於新用戶,請使用“登錄”按鈕首次在您的應用程序中登錄

262535d1b1223c65.png

  1. 登錄後,將自動顯示歡迎消息:

1c70e0d64b23525b.png

用戶可以在聊天中上載所有類型的圖像,並且適度冒犯性圖像始終很重要,尤其是在公共社交平台中。在FriendlyChat中,將發佈到聊天室中的圖像存儲到Google Cloud Storage中

使用Cloud Functions,您可以使用functions.storage().onFinalize觸發器來檢測新的圖像上傳。每當在Cloud Storage中上傳或修改新文件時,此操作就會運行。

要審核圖像,我們將執行以下過程:

  1. 使用Cloud Vision API檢查圖像是否標記為成人或暴力
  2. 如果圖像已被標記,則將其下載到正在運行的Functions實例上
  3. 使用ImageMagick模糊圖像
  4. 將模糊的圖像上傳到Cloud Storage

啟用Cloud Vision API

由於我們將在此功能中使用Google Cloud Vision API,因此您必須在Firebase項目上啟用該API。點擊此鏈接,選擇您的Firebase項目並啟用API:

5c77fee51ec5de49.png

安裝依賴項

要審核圖像,我們需要一些Node.js包:

  • 適用於Node.js的Google Cloud Vision客戶端庫: @ google-cloud / vision ,可通過Cloud Vision API運行圖像以檢測不適當的圖像。
  • 一個Node.js庫,允許我們運行進程:子進程承諾運行ImageMagick,因為ImageMagick命令行工具已預先安裝在所有Functions實例上。

要將這兩個軟件包安裝到您的Cloud Functions應用中,請運行以下npm install --save命令。確保您從functions目錄執行此操作。

npm install --save @google-cloud/vision@0.12.0 child-process-promise@2.2.1

這將在本地安裝這兩個軟件包,並將它們作為已聲明的依賴項添加到package.json文件中。

導入和配置依賴項

要導入已安裝的兩個依賴項以及本節中需要的一些Node.js核心模塊( pathosfs ),請在index.js文件頂部添加以下幾行:

index.js

const Vision = require('@google-cloud/vision');
const vision = new Vision();
const spawn = require('child-process-promise').spawn;

const path = require('path');
const os = require('os');
const fs = require('fs');

由於您的功能將在Google Cloud環境中運行,因此無需配置Cloud Storage和Cloud Vision庫:它們將自動配置為使用您的項目。

檢測不合適的圖像

您將使用functions.storage.onChange Cloud Functions觸發器,該觸發器將在Cloud Storage存儲桶中創建或修改文件或文件夾後立即運行代碼。將blurOffensiveImages函數添加到index.js文件中:

index.js

// Checks if uploaded images are flagged as Adult or Violence and if so blurs them.
exports.blurOffensiveImages = functions.runWith({memory: '2GB'}).storage.object().onFinalize(
    async (object) => {
      const image = {
        source: {imageUri: `gs://${object.bucket}/${object.name}`},
      };

      // Check the image content using the Cloud Vision API.
      const batchAnnotateImagesResponse = await vision.safeSearchDetection(image);
      const safeSearchResult = batchAnnotateImagesResponse[0].safeSearchAnnotation;
      const Likelihood = Vision.types.Likelihood;
      if (Likelihood[safeSearchResult.adult] >= Likelihood.LIKELY ||
          Likelihood[safeSearchResult.violence] >= Likelihood.LIKELY) {
        console.log('The image', object.name, 'has been detected as inappropriate.');
        return blurImage(object.name);
      }
      console.log('The image', object.name, 'has been detected as OK.');
    });

請注意,我們添加了將運行該函數的Cloud Functions實例的一些配置,我們使用.runWith({memory: '2GB'})請求該實例獲取2GB的內存而不是默認的內存,這將有所幫助函數是佔用大量內存的。

觸發該功能後,將通過Cloud Vision API運行該圖像,以檢測該圖像是否標記為成人或暴力。如果根據這些標準將圖像檢測為不適當的圖像,我們將對圖像進行模糊處理,這將在blurImage函數中完成,我們將在下面看到。

圖像模糊

index.js文件中添加以下blurImage函數:

index.js

// Blurs the given image located in the given bucket using ImageMagick.
async function blurImage(filePath) {
  const tempLocalFile = path.join(os.tmpdir(), path.basename(filePath));
  const messageId = filePath.split(path.sep)[1];
  const bucket = admin.storage().bucket();

  // Download file from bucket.
  await bucket.file(filePath).download({destination: tempLocalFile});
  console.log('Image has been downloaded to', tempLocalFile);
  // Blur the image using ImageMagick.
  await spawn('convert', [tempLocalFile, '-channel', 'RGBA', '-blur', '0x24', tempLocalFile]);
  console.log('Image has been blurred');
  // Uploading the Blurred image back into the bucket.
  await bucket.upload(tempLocalFile, {destination: filePath});
  console.log('Blurred image has been uploaded to', filePath);
  // Deleting the local file to free up disk space.
  fs.unlinkSync(tempLocalFile);
  console.log('Deleted local file.');
  // Indicate that the message has been moderated.
  await admin.firestore().collection('messages').doc(messageId).update({moderated: true});
  console.log('Marked the image as moderated in the database.');
}

在上述功能中,映像二進製文件是從Cloud Storage下載的。然後,使用ImageMagick的convert工具對圖像進行模糊處理,然後convert模糊的版本重新上傳到存儲桶中。然後,我們刪除Cloud Functions實例上的文件以釋放一些磁盤空間,這是因為相同的Cloud Functions實例可以重新使用,如果未清理文件,則磁盤可能用完了。最後,我們在聊天消息中添加一個布爾值,指示圖像已被審核,這將觸發客戶端上消息的刷新。

部署功能

該功能僅在部署後才處於活動狀態。在命令行上運行firebase deploy --only functions

firebase deploy --only functions

這是您應該看到的控制台輸出:

i  deploying functions
i  functions: ensuring necessary APIs are enabled...
✔  functions: all necessary APIs are enabled
i  functions: preparing functions directory for uploading...
i  functions: packaged functions (X.XX KB) for uploading
✔  functions: functions folder uploaded successfully
i  starting release process (may take several minutes)...
i  functions: updating function addWelcomeMessages...
i  functions: creating function blurOffensiveImages...
✔  functions[addWelcomeMessages]: Successful update operation.
✔  functions[blurOffensiveImages]: Successful create operation.
✔  functions: all functions deployed successfully!

✔  Deploy complete!

Project Console: https://console.firebase.google.com/project/friendlychat-1234/overview

測試功能

功能成功部署後:

  1. 使用託管URL(以https://<project-id>.firebaseapp.com的形式)在瀏覽器中打開您的應用程序。
  2. 登錄應用後,上傳圖片: 4db9fdab56703e4a.png
  3. 選擇要上傳的最佳進攻圖像(或者您可以使用這張吃殭屍的肉!),過一會兒,您應該會看到圖像模糊不清,您的帖子會刷新: 83dd904fbaf97d2b.png

在本部分中,您將添加一個Cloud Function,該功能會在發布新消息時向聊天參與者發送通知。

使用Firebase Cloud Messaging (FCM),您可以跨平台且可靠的方式向用戶發送通知。要將通知發送給用戶,您需要他們的FCM設備令牌。當用戶首次在新的瀏覽器或設備上打開應用程序時,我們正在使用的聊天網絡應用程序已從用戶那裡收集設備令牌。這些令牌存儲在fcmTokens集合中的Cloud Firestore中。

如果您想學習如何在Web應用程序上獲取FCM設備令牌,可以通過Firebase Web Codelab

發送通知

要檢測何時發布新消息,您將使用functions.firestore.document().onCreate Cloud Functions觸發器,該觸發器在Cloud Firestore的給定路徑上創建新對象時運行代碼。將sendNotifications函數添加到index.js文件中:

index.js

// Sends a notifications to all users when a new message is posted.
exports.sendNotifications = functions.firestore.document('messages/{messageId}').onCreate(
  async (snapshot) => {
    // Notification details.
    const text = snapshot.data().text;
    const payload = {
      notification: {
        title: `${snapshot.data().name} posted ${text ? 'a message' : 'an image'}`,
        body: text ? (text.length <= 100 ? text : text.substring(0, 97) + '...') : '',
        icon: snapshot.data().profilePicUrl || '/images/profile_placeholder.png',
        click_action: `https://${process.env.GCLOUD_PROJECT}.firebaseapp.com`,
      }
    };

    // Get the list of device tokens.
    const allTokens = await admin.firestore().collection('fcmTokens').get();
    const tokens = [];
    allTokens.forEach((tokenDoc) => {
      tokens.push(tokenDoc.id);
    });

    if (tokens.length > 0) {
      // Send notifications to all tokens.
      const response = await admin.messaging().sendToDevice(tokens, payload);
      await cleanupTokens(response, tokens);
      console.log('Notifications have been sent and tokens cleaned up.');
    }
  });

在上面的函數中,我們從Cloud Firestore數據庫收集所有用戶的設備令牌,並使用admin.messaging().sendToDevice函數向每個令牌發送通知。

清理令牌

最後,我們要刪除不再有效的令牌。當我們曾經從用戶那裡獲得的令牌不再被瀏覽器或設備使用時,就會發生這種情況。例如,如果用戶已撤銷其瀏覽器會話的通知權限,則會發生這種情況。為此,在index.js文件中添加以下cleanupTokens函數:

index.js

// Cleans up the tokens that are no longer valid.
function cleanupTokens(response, tokens) {
 // For each notification we check if there was an error.
 const tokensDelete = [];
 response.results.forEach((result, index) => {
   const error = result.error;
   if (error) {
     console.error('Failure sending notification to', tokens[index], error);
     // Cleanup the tokens who are not registered anymore.
     if (error.code === 'messaging/invalid-registration-token' ||
         error.code === 'messaging/registration-token-not-registered') {
       const deleteTask = admin.firestore().collection('fcmTokens').doc(tokens[index]).delete();
       tokensDelete.push(deleteTask);
     }
   }
 });
 return Promise.all(tokensDelete);
}

部署功能

該功能僅在部署後才處於活動狀態。在命令行上運行firebase deploy --only functions

firebase deploy --only functions

這是您應該看到的控制台輸出:

i  deploying functions
i  functions: ensuring necessary APIs are enabled...
✔  functions: all necessary APIs are enabled
i  functions: preparing functions directory for uploading...
i  functions: packaged functions (X.XX KB) for uploading
✔  functions: functions folder uploaded successfully
i  starting release process (may take several minutes)...
i  functions: updating function addWelcomeMessages...
i  functions: updating function blurOffensiveImages...
i  functions: creating function sendNotifications...
✔  functions[addWelcomeMessages]: Successful update operation.
✔  functions[blurOffensiveImages]: Successful updating operation.
✔  functions[sendNotifications]: Successful create operation.
✔  functions: all functions deployed successfully!

✔  Deploy complete!

Project Console: https://console.firebase.google.com/project/friendlychat-1234/overview

測試功能

  1. 功能成功部署後,使用託管URL(以https://<project-id>.firebaseapp.com的形式)在瀏覽器中打開您的應用程序。
  2. 如果您是首次登錄應用,請確保在出現提示時允許通知: 8b9d0c66dc36153d.png
  3. 關閉聊天應用程序選項卡或顯示其他選項卡:僅當應用程序在後台時,才會顯示通知。如果您想了解如何在前台運行應用程序時接收消息,請查看我們的文檔
  4. 使用其他瀏覽器(或隱身窗口),登錄應用並發布消息。您應該看到第一個瀏覽器顯示的通知: 45282ab12b28b926.png

您已使用Firebase SDK for Cloud Functions並將服務器端組件添加到聊天應用程序中。

我們涵蓋的內容

  • 使用Firebase SDK for Cloud Functions創作Cloud Functions。
  • 根據Auth,Cloud Storage和Cloud Firestore事件觸發Cloud Functions。
  • 將Firebase Cloud Messaging支持添加到您的Web應用程序。
  • 使用Firebase CLI部署的雲功能。

下一步

了解更多