Ir para o console

Chamar funções a partir do seu aplicativo

Com os SDKs do cliente do Cloud Functions para Firebase, você pode chamar funções diretamente de um app do Firebase. Para fazer isso, escreva e implante uma função HTTPS chamável no Cloud Functions e adicione a lógica do cliente para chamar a função do seu app.

As funções chamáveis são semelhantes a outras funções HTTP, com os seguintes recursos adicionais:

  • Com as funções chamáveis, os tokens do Firebase Authentication e do FCM são incluídos automaticamente nas solicitações quando estiverem disponíveis.
  • O acionador functions.https.onCall desserializa automaticamente o corpo da solicitação e valida os tokens de autenticação.

O Firebase SDK para Cloud Functions v0.9.1 e versões posteriores opera com essas versões mínimas do SDK do cliente do Firebase para oferecer compatibilidade com funções HTTPS chamáveis:

  • SDK do Firebase para iOS 6.2.0
  • SDK do Firebase para Android 17.0.0
  • SDK do Firebase para JavaScript 6.1.1

Se você quer adicionar um recurso semelhante a um aplicativo integrado em uma plataforma sem suporte, consulte Especificação do protocolo para https.onCall. Você verá instruções na outra parte deste guia sobre como escrever, implantar e chamar uma função HTTPS chamável para iOS, Android, Web, C ++ e Unity.

Escrever e implantar a função chamável

Use functions.https.onCall para criar uma função HTTPS chamável. Esse método tem dois parâmetros: data e context opcional:

// Saves a message to the Firebase Realtime Database but sanitizes the text by removing swearwords.
exports.addMessage = functions.https.onCall((data, context) => {
  // ...
});

Para uma função chamável que salva uma mensagem de texto para o Realtime Database, por exemplo, data pode conter o texto da mensagem, enquanto os parâmetros context representam a informação de autenticação do usuário:

// Message text passed from the client.
const text = data.text;// Authentication / user information is automatically added to the request.
const uid = context.auth.uid;
const name = context.auth.token.name || null;
const picture = context.auth.token.picture || null;
const email = context.auth.token.email || null;

A distância entre o local da função chamável e o do cliente que faz o chamado pode criar uma latência de rede significativa. Para otimizar o desempenho, especifique o local da função, quando aplicável, e alinhe o local da função chamável com o local definido ao inicializar o SDK no cliente.

Como enviar o resultado de volta

Para enviar dados de volta para o cliente, retorne dados que podem ser codificados com JSON. Por exemplo, para retornar o resultado de uma operação de adição:

// returning result.
return {
  firstNumber: firstNumber,
  secondNumber: secondNumber,
  operator: '+',
  operationResult: firstNumber + secondNumber,
};

Para retornar dados após uma operação assíncrona, retorne uma promessa. Os dados retornados pela promessa são enviados de volta ao cliente. Por exemplo, você pode retornar o texto limpo que a função chamável escreveu no Realtime Database:

// Saving the new message to the Realtime Database.
const sanitizedMessage = sanitizer.sanitizeText(text); // Sanitize the message.
return admin.database().ref('/messages').push({
  text: sanitizedMessage,
  author: { uid, name, picture, email },
}).then(() => {
  console.log('New Message written');
  // Returning the sanitized message to the client.
  return { text: sanitizedMessage };
})

Como solucionar erros

Para garantir que o cliente receba detalhes de erro úteis, retorne erros de uma função chamável ao emitir uma instância functions.https.HttpsError ou retornar uma promessa recusada com essa instância. O erro tem um atributo code que pode ser um dos valores listados em functions.https.HttpsError. Os erros também têm uma string message, que tem como padrão uma string vazia. Eles também podem ter um campo details opcional com um valor arbitrário. Se um erro diferente de HttpsError for emitido pelas suas funções, seu cliente receberá um erro com a mensagem INTERNAL e o código internal.

Por exemplo, uma função pode emitir erros de validação de dados e autenticação com mensagens de erro para retornar ao cliente que faz o chamado:

// Checking attribute.
if (!(typeof text === 'string') || text.length === 0) {
  // Throwing an HttpsError so that the client gets the error details.
  throw new functions.https.HttpsError('invalid-argument', 'The function must be called with ' +
      'one arguments "text" containing the message text to add.');
}
// Checking that the user is authenticated.
if (!context.auth) {
  // Throwing an HttpsError so that the client gets the error details.
  throw new functions.https.HttpsError('failed-precondition', 'The function must be called ' +
      'while authenticated.');
}

Como implantar a função chamável

Depois que você salva uma função chamável completa dentro do index.js, ela é implantada com todas as outras funções quando você executa firebase deploy. Para implantar somente a função chamável, use o argumento --only conforme mostrado para executar implantações parciais:

$ firebase deploy --only functions:addMessage

Como configurar seu ambiente de desenvolvimento de cliente

Verifique se você cumpre todos os pré-requisitos e adicione as dependências e bibliotecas de clientes necessárias ao seu app.

iOS

  1. Siga as instruções para adicionar o Firebase ao seu app para iOS.
  2. Adicione os pods do Firebase Core e do Cloud Functions ao seu Podfile:
    pod 'Firebase/Analytics'
    pod 'Firebase/Functions'
  3. Salve o arquivo e execute:
    pod install

Web

  1. Siga as instruções para adicionar o Firebase ao seu app da Web.
  2. Adicione as bibliotecas de cliente do Firebase Core e do Cloud Functions ao seu app:
    <script src="https://www.gstatic.com/firebasejs/6.1.1/firebase.js"></script>
    <script src="https://www.gstatic.com/firebasejs/6.1.1/firebase-functions.js"></script>
    

O SDK do Cloud Functions também está disponível como um pacote npm.

  1. Execute o seguinte comando no seu terminal:
    npm install firebase@6.1.1 --save
    
  2. Requisite manualmente o Firebase Core e o Cloud Functions:
    const firebase = require("firebase");
    // Required for side-effects
    require("firebase/functions");
    

Android

  1. Siga as instruções para adicionar o Firebase ao seu app para Android.
  2. No arquivo build.gradle do nível do projeto, certifique-se de incluir o repositório Maven do Google nas seções buildscript e allprojects.
  3. Adicione a dependência para a biblioteca do Cloud Functions para Android ao seu arquivo Gradle do módulo (nível de aplicativo) (geralmente app/build.gradle ):
    implementation 'com.google.firebase:firebase-functions:17.0.0'
    

C++

Para C ++ com Android:

  1. Siga as instruções para adicionar o Firebase ao seu projeto em C++.
  2. No arquivo build.gradle do nível de projeto, certifique-se de incluir repositório Maven do Google, nas seções buildscript e allprojects.
  3. Adicione a biblioteca do firebase_functions ao arquivo CMakeLists.txt.

Para o C ++ com iOS:

  1. Siga as instruções para adicionar o Firebase ao seu projeto em C++.
  2. Adicione os pods do Firebase Core e do Cloud Functions ao seu Podfile:
    pod 'Firebase/Analytics'
    pod 'Firebase/Functions'
  3. Salve o arquivo e execute:
    pod install
  4. Adicione o Firebase Core e os frameworks do Cloud Functions do SDK do Firebase para C++ ao seu projeto do Xcode.
    • firebase.framework
    • firebase_functions.framework

Unity

  1. Siga as instruções para adicionar o Firebase ao seu projeto do Unity.
  2. Adicione o FirebaseFunctions.unitypackage do SDK do Firebase para Unity ao seu projeto do Unity.

Como inicializar o SDK do cliente

Inicialize uma instância do Cloud Functions:

Swift

lazy var functions = Functions.functions()

Objective-C

@property(strong, nonatomic) FIRFunctions *functions;// ...
self.functions = [FIRFunctions functions];

Web

firebase.initializeApp({
  apiKey: '### FIREBASE API KEY ###',
  authDomain: '### FIREBASE AUTH DOMAIN ###',
  projectId: '### CLOUD FUNCTIONS PROJECT ID ###'
  databaseURL: 'https://### YOUR DATABASE NAME ###.firebaseio.com',
});

// Initialize Cloud Functions through Firebase
var functions = firebase.functions();

Java

private FirebaseFunctions mFunctions;// ...
mFunctions = FirebaseFunctions.getInstance();

Kotlin

private lateinit var functions: FirebaseFunctions// ...
functions = FirebaseFunctions.getInstance()

C++

firebase::functions::Functions* functions;
// ...
functions = firebase::functions::Functions::GetInstance(app);

Unity

functions = Firebase.Functions.DefaultInstance;

Como chamar a função

Swift

functions.httpsCallable("addMessage").call(["text": inputField.text]) { (result, error) in
  if let error = error as NSError? {
    if error.domain == FunctionsErrorDomain {
      let code = FunctionsErrorCode(rawValue: error.code)
      let message = error.localizedDescription
      let details = error.userInfo[FunctionsErrorDetailsKey]
    }
    // ...
  }
  if let text = (result?.data as? [String: Any])?["text"] as? String {
    self.resultField.text = text
  }
}

Objective-C

[[_functions HTTPSCallableWithName:@"addMessage"] callWithObject:@{@"text": _inputField.text}
                                                      completion:^(FIRHTTPSCallableResult * _Nullable result, NSError * _Nullable error) {
  if (error) {
    if (error.domain == FIRFunctionsErrorDomain) {
      FIRFunctionsErrorCode code = error.code;
      NSString *message = error.localizedDescription;
      NSObject *details = error.userInfo[FIRFunctionsErrorDetailsKey];
    }
    // ...
  }
  self->_resultField.text = result.data[@"text"];
}];

Web

var addMessage = firebase.functions().httpsCallable('addMessage');
addMessage({text: messageText}).then(function(result) {
  // Read result of the Cloud Function.
  var sanitizedMessage = result.data.text;
  // ...
});

Java

private Task<String> addMessage(String text) {
    // Create the arguments to the callable function.
    Map<String, Object> data = new HashMap<>();
    data.put("text", text);
    data.put("push", true);

    return mFunctions
            .getHttpsCallable("addMessage")
            .call(data)
            .continueWith(new Continuation<HttpsCallableResult, String>() {
                @Override
                public String then(@NonNull Task<HttpsCallableResult> task) throws Exception {
                    // This continuation runs on either success or failure, but if the task
                    // has failed then getResult() will throw an Exception which will be
                    // propagated down.
                    String result = (String) task.getResult().getData();
                    return result;
                }
            });
}

Kotlin

private fun addMessage(text: String): Task<String> {
    // Create the arguments to the callable function.
    val data = hashMapOf(
        "text" to text,
        "push" to true
    )

    return functions
            .getHttpsCallable("addMessage")
            .call(data)
            .continueWith { task ->
                // This continuation runs on either success or failure, but if the task
                // has failed then result will throw an Exception which will be
                // propagated down.
                val result = task.result?.data as String
                result
            }
}

C++

firebase::Future<firebase::functions::HttpsCallableResult> AddMessage(
    const string& text) {
  // Create the arguments to the callable function.
  firebase::Variant data = firebase::Variant::EmptyMap();
  data.map()["text"] = firebase::Variant(text);
  data.map()["push"] = true;

  // Call the function and add a callback for the result.
  firebase::functions::HttpsCallableReference doSomething =
      functions->GetHttpsCallable("addMessage");
  return doSomething.Call(data);
}

Unity

private Task<string> addMessage(string text) {
  // Create the arguments to the callable function.
  var data = new Dictionary<string, object>();
  data["text"] = text;
  data["push"] = true;

  // Call the function and extract the operation from the result.
  var function = functions.GetHttpsCallable("addMessage");
  return function.CallAsync(data).ContinueWith((task) => {
    return (string) task.Result.Data;
  });
}

Como solucionar erros no cliente

O cliente receberá um erro se o servidor emitir um erro ou se a promessa resultante for recusada.

Se o erro retornado pela função for do tipo function.https.HttpsError, o cliente receberá code, message e details do erro do servidor. Caso contrário, o erro conterá a mensagem INTERNAL e o código INTERNAL. Consulte as orientações sobre como solucionar erros na sua função chamável.

Swift

if let error = error as NSError? {
  if error.domain == FunctionsErrorDomain {
    let code = FunctionsErrorCode(rawValue: error.code)
    let message = error.localizedDescription
    let details = error.userInfo[FunctionsErrorDetailsKey]
  }
  // ...
}

Objective-C

if (error) {
  if (error.domain == FIRFunctionsErrorDomain) {
    FIRFunctionsErrorCode code = error.code;
    NSString *message = error.localizedDescription;
    NSObject *details = error.userInfo[FIRFunctionsErrorDetailsKey];
  }
  // ...
}

Web

var addMessage = firebase.functions().httpsCallable('addMessage');
addMessage({text: messageText}).then(function(result) {
  // Read result of the Cloud Function.
  var sanitizedMessage = result.data.text;}).catch(function(error) {
  // Getting the Error details.
  var code = error.code;
  var message = error.message;
  var details = error.details;
  // ...
});

Java

addMessage(inputMessage)
        .addOnCompleteListener(new OnCompleteListener<String>() {
            @Override
            public void onComplete(@NonNull Task<String> task) {
                if (!task.isSuccessful()) {
                    Exception e = task.getException();
                    if (e instanceof FirebaseFunctionsException) {
                        FirebaseFunctionsException ffe = (FirebaseFunctionsException) e;
                        FirebaseFunctionsException.Code code = ffe.getCode();
                        Object details = ffe.getDetails();
                    }

                    // ...
                }

                // ...
            }
        });

Kotlin

addMessage(inputMessage)
        .addOnCompleteListener(OnCompleteListener { task ->
            if (!task.isSuccessful) {
                val e = task.exception
                if (e is FirebaseFunctionsException) {
                    val code = e.code
                    val details = e.details
                }

                // ...
            }

            // ...
        })

C++

void OnAddMessageCallback(
    const firebase::Future<firebase::functions::HttpsCallableResult>& future) {
  if (future.error() != firebase::functions::kErrorNone) {
    // Function error code, will be kErrorInternal if the failure was not
    // handled properly in the function call.
    auto code = static_cast<firebase::functions::Error>(future.error());

    // Display the error in the UI.
    DisplayError(code, future.error_message());
    return;
  }

  const firebase::functions::HttpsCallableResult *result = future.result();
  firebase::Variant data = result->data();
  // This will assert if the result returned from the function wasn't a string.
  string message = data.string_value();
  // Display the result in the UI.
  DisplayResult(message);
}

// ...

// ...
  auto future = AddMessage(message);
  future.OnCompletion(OnAddMessageCallback);
// ...

Unity

 addMessage(text).ContinueWith((task) => {
  if (task.IsFaulted) {
    foreach (var inner in task.Exception.InnerExceptions) {
      if (inner is FunctionsException) {
        var e = (FunctionsException) inner;
        // Function error code, will be INTERNAL if the failure
        // was not handled properly in the function call.
        var code = e.ErrorCode;
        var message = e.ErrorMessage;
      }
    }
  } else {
    string result = task.Result;
  }
});