Compartilhar via


Falhas no App Center (tvOS)

Importante

O Visual Studio App Center foi desativado em 31 de março de 2025, com exceção dos recursos de Análise e Diagnóstico, que continuarão com suporte até 30 de junho de 2026. Saiba mais.

As falhas do App Center gerarão automaticamente um log de falhas sempre que o aplicativo falhar. O log é gravado pela primeira vez no armazenamento do dispositivo e, quando o usuário inicia o aplicativo novamente, o relatório de falha será enviado para o App Center. A coleta de falhas funciona para aplicativos beta e ao vivo, ou seja, aqueles enviados para a App Store. Os logs de falha contêm informações valiosas para ajudar a corrigir a falha.

Siga a seção Introdução se você ainda não configurou o SDK em seu aplicativo.

Além disso, os logs de falhas na tvOS exigem a Simbolização, confira a documentação de Diagnóstico do App Center que explica como fornecer símbolos para seu aplicativo.

Observação

Para receber rastreamentos de pilha devidamente simbolizados, verifique se o bitcode está desabilitado. Você pode saber mais sobre o bitcode na documentação de Simbolização do iOS do App Center.

Observação

Na versão 4.0.0 do App Center, foram introduzidas alterações de ruptura. Siga a seção Migrar para o SDK do App Center 4.0.0 e superior para migrar o App Center de versões anteriores.

Gerar uma falha de teste

O App Center Crashes fornece uma API para simular um crash de teste, facilitando o teste do SDK. Essa API só pode ser usada em aplicativos de teste/beta e não fará nada em aplicativos de produção.

[MSACCrashes generateTestCrash];
Crashes.generateTestCrash()

Obter mais informações sobre uma falha anterior

O App Center Crashes tem duas APIs que fornecem mais informações caso o aplicativo tenha falhado.

O aplicativo recebeu um aviso de memória baixa na sessão anterior?

A qualquer momento após iniciar o SDK, você pode verificar se o aplicativo recebeu um aviso de memória na sessão anterior:

[MSACCrashes hasReceivedMemoryWarningInLastSession];
Crashes.hasReceivedMemoryWarningInLastSession

Observação

Esse método só deve ser usado depois Crashes de iniciado, ele sempre retornará NO ou false antes de começar.

Observação

Em alguns casos, um dispositivo com memória baixa não pode enviar eventos.

O aplicativo falhou na sessão anterior?

A qualquer momento após iniciar o SDK, você pode verificar se o aplicativo falhou na inicialização anterior:

[MSACCrashes hasCrashedInLastSession];
Crashes.hasCrashedInLastSession

Isso é útil caso você deseje ajustar o comportamento ou a interface do usuário do seu aplicativo depois que ocorreu uma falha.

Observação

Esse método só deve ser usado depois MSACCrashes de iniciado, ele sempre retornará NO ou false antes de começar.

Detalhes sobre a última falha

Se o aplicativo falhou anteriormente, você pode obter detalhes sobre a última falha.

MSACErrorReport *crashReport = [MSACCrashes lastSessionCrashReport];
var crashReport = Crashes.lastSessionCrashReport

Observação

Esse método só deve ser usado depois Crashes de iniciado, ele sempre retornará nil antes do início.

Há vários casos de uso para essa API, o mais comum são as pessoas que chamam essa API e implementam seu CrashesDelegate personalizado.

Personalize o uso do recurso de falhas do App Center

O App Center Crashes fornece retornos de chamada para os desenvolvedores executarem ações adicionais antes de enviar e ao enviar relatórios de falhas para o App Center.

Para adicionar seu comportamento personalizado, você precisa adotar o CrashesDelegate-protocolo, todos os seus métodos são opcionais.

Registrar-se como um delegado

[MSACCrashes setDelegate:self];
Crashes.delegate = self

Observação

Você deve definir o delegado antes da chamada AppCenter.start, já que o App Center inicia o processamento de falhas imediatamente após a inicialização.

A falha deve ser processada?

Implemente o crashes:shouldProcessErrorReport:método na classe que adota o CrashesDelegateprotocolo se você quiser decidir se uma falha específica precisa ser processada ou não. Por exemplo, pode haver uma falha no nível do sistema que você deseja ignorar e que não deseja enviar para o App Center.

- (BOOL)crashes:(MSACCrashes *)crashes shouldProcessErrorReport:(MSACErrorReport *)errorReport {
  return YES; // return YES if the crash report should be processed, otherwise NO.
}
func crashes(_ crashes: Crashes, shouldProcess errorReport: ErrorReport) -> Bool {
  return true; // return true if the crash report should be processed, otherwise false.
}

Erros tratados

O App Center também permite que você rastreie erros usando exceções manipuladas por meio do trackError método. Opcionalmente, um aplicativo pode anexar propriedades ou/e anexos a um relatório de erros manipulado para fornecer mais contexto.

@try {
  // Throw error.
} @catch (NSError *error) {

  // Init attachments.
  NSArray<MSACErrorAttachmentLog *> attachments = @[ MSACErrorAttachmentLog attachmentWithText:@"Hello world!" filename:@"hello.txt"] ]

  // Init properties.
  NSDictionary *properties = @{ "Category" : "Music", "Wifi" : "On" };

  // Track errors.
  [MSACCrashes trackError:error withProperties:properties attachments:attachments];
  [MSACCrashes trackError:error withProperties:properties attachments:nil];
  [MSACCrashes trackError:error withProperties:nil attachments:attachments];
  [MSACCrashes trackError:error withProperties:nil attachments:nil];
}
do {
  // Throw error.
} catch {

  // Init attachments.
  let attachments = [ErrorAttachmentLog.attachment(withText: "Hello world!", filename: "hello.txt")]

  // Init properties.
  let properties:Dictionary<String, String> = ["Category" : "Music", "Wifi" : "On"]

  // Track errors.
  Crashes.trackError(error, properties: properties, attachments: attachments)
  Crashes.trackError(error, properties: properties, attachments: nil)
  Crashes.trackError(error, properties: nil, attachments: attachments)
  Crashes.trackError(error, properties: nil, attachments: nil)
}

Para acompanhar exceções, você pode usar o trackException método:

@try {
  // Throw exceptions.
} @catch (NSException *exception) {

  // Init exceptions.
  MSACExceptionModel *customException1 = [MSACExceptionModel initWithType:@"Custom exception" exceptionMessage:"Track custom exception.", stackTrace:exception.callStackSymbols];
  MSACExceptionModel *customException2 = [MSACExceptionModel initWithException:exception];

  // Track exceptions.
  [MSACCrashes trackException:customException1 withProperties:properties attachments:nil];
  [MSACCrashes trackException:customException2 withProperties:properties attachments:nil];
}
do {
  // Throw exception.
} catch {

  // Init exception.
  let exception = ExceptionModel(withType: "Custom exception", exceptionMessage: "Track custom exception.", stackTrace: Thread.callStackSymbols)

  // Track exception.
  Crashes.trackException(exception, properties: properties, attachments: nil)
}

Se a privacidade do usuário for importante para você, talvez você queira obter a confirmação dos usuários antes de enviar um relatório de falha para o App Center. O SDK expõe um callback que instrui o App Center Crashes a aguardar a confirmação dos usuários antes de enviar qualquer relatório de falha.

Se você optar por fazer isso, será responsável por obter a confirmação do usuário, por exemplo, por meio de um prompt de diálogo com uma das seguintes opções: Sempre enviar, Enviar e Não enviar. Baseado na entrada, você informará à Central de Aplicativos Crashes o que fazer e a falha será tratada adequadamente.

Observação

O SDK não exibe uma caixa de diálogo para isso, o aplicativo deve fornecer sua própria interface do usuário para solicitar o consentimento do usuário.

Observação

O aplicativo não deverá chamar notifyWithUserConfirmation explicitamente se não implementar uma caixa de diálogo de confirmação do usuário; o módulo Crashes manipulará o envio de logs para você implicitamente.

O método a seguir mostra como configurar um manipulador de confirmação do usuário:

[MSACCrashes setUserConfirmationHandler:(^(NSArray<MSACErrorReport *> *errorReports) {

  // Your code to present your UI to the user, e.g. an UIAlertController.
  UIAlertController *alertController = [UIAlertController
      alertControllerWithTitle:@"Sorry about that!"
                      message:@"Do you want to send an anonymous crash report so we can fix the issue?"
                preferredStyle:UIAlertControllerStyleAlert];

  [alertController
      addAction:[UIAlertAction actionWithTitle:@"Don't send"
                                        style:UIAlertActionStyleCancel
                                      handler:^(UIAlertAction *action) {
                                        [MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationDontSend];
                                      }]];

  [alertController
      addAction:[UIAlertAction actionWithTitle:@"Send"
                                        style:UIAlertActionStyleDefault
                                      handler:^(UIAlertAction *action) {
                                        [MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationSend];
                                      }]];

  [alertController
      addAction:[UIAlertAction actionWithTitle:@"Always send"
                                        style:UIAlertActionStyleDefault
                                      handler:^(UIAlertAction *action) {
                                        [MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationAlways];
                                      }]];
  // Show the alert controller.
  [self.window.rootViewController presentViewController:alertController animated:YES completion:nil];
  return YES; // Return YES if the SDK should await user confirmation, otherwise NO.
})];
MSACCrashes.setUserConfirmationHandler({ (errorReports: [MSACErrorReport]) in

  // Your code to present your UI to the user, e.g. an UIAlertController.
  let alertController = UIAlertController(title: "Sorry about that!",
                                          message: "Do you want to send an anonymous crash report so we can fix the issue?",
                                          preferredStyle:.alert)

  alertController.addAction(UIAlertAction(title: "Don't send", style: .cancel) {_ in
    MSACCrashes.notify(with: .dontSend)
  })

  alertController.addAction(UIAlertAction(title: "Send", style: .default) {_ in
    MSACCrashes.notify(with: .send)
  })

  alertController.addAction(UIAlertAction(title: "Always send", style: .default) {_ in
    MSACCrashes.notify(with: .always)
  })

  // Show the alert controller.
  self.window?.rootViewController?.present(alertController, animated: true)
  return true // Return true if the SDK should await user confirmation, otherwise return false.
})

Caso você retorne YES/true no bloco de manipuladores acima, seu aplicativo deverá obter permissão de usuário e enviar uma mensagem ao SDK com o resultado usando a API a seguir. Se você estiver usando um alerta para isso, como fazemos no exemplo acima, você o chamará de dentro da implementação do alertView:clickedButtonAtIndex:-callback.

// Depending on the users's choice, call notifyWithUserConfirmation: with the right value.
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationDontSend];
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationSend];
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationAlways];
// Depending on the user's choice, call notify(with:) with the right value.
MSACCrashes.notify(with: .dontSend)
MSACCrashes.notify(with: .send)
MSACCrashes.notify(with: .always)

Obter informações sobre o status de envio de um relatório de erro

Às vezes, você deseja saber o status da falha do aplicativo. Um caso de uso comum é que talvez você queira mostrar a interface do usuário que informa aos usuários que seu aplicativo está enviando um relatório de falha ou, caso seu aplicativo esteja falhando rapidamente após a inicialização, você deseja ajustar o comportamento do aplicativo para garantir que os logs de falha possam ser enviados. O protocolo CrashesDelegate define três callbacks diferentes que você pode usar em seu aplicativo para receber notificações sobre o que está acontecendo.

O retorno de chamada a seguir será invocado antes que o SDK envie um log de falhas

- (void)crashes:(MSACCrashes *)crashes willSendErrorReport:(MSACErrorReport *)errorReport {
  // Your code, e.g. to present a custom UI.
}
func crashes(_ crashes: Crashes, willSend errorReport: ErrorReport) {
  // Your code, e.g. to present a custom UI.
}

Caso tenhamos problemas de rede ou uma interrupção no ponto de extremidade e você reinicie o aplicativo, willSendErrorReport será disparado novamente após a reinicialização do processo.

O retorno de chamada a seguir será invocado depois que o SDK enviou um log de falhas com êxito

- (void)crashes:(MSACCrashes *)crashes didSucceedSendingErrorReport:(MSACErrorReport *)errorReport {
  // Your code, e.g. to hide the custom UI.
}
func crashes(_ crashes: Crashes, didSucceedSending errorReport: ErrorReport) {
  // Your code goes here.
}

O retorno de chamada a seguir será invocado se o SDK não tiver enviado um crash log

- (void)crashes:(MSACCrashes *)crashes didFailSendingErrorReport:(MSACErrorReport *)errorReport withError:(NSError *)error {
  // Your code goes here.
}
func crashes(_ crashes: Crashes, didFailSending errorReport: ErrorReport, withError error: Error) {
  // Your code goes here.
}

O recebimento didFailSendingErrorReport significa que ocorreu um erro não recuperável, como um código 4xx . Por exemplo, 401 significa que está appSecret errado.

Esse retorno de chamada não será ativado se for um problema de rede. Nesse caso, o SDK continua tentando novamente (e também pausa novas tentativas enquanto a conexão de rede está inativa).

Adicionar anexos a um relatório de falha

Você pode adicionar anexos binários e de texto a um relatório de falha. O SDK enviará essas informações junto com a falha, para que você possa vê-las no portal do App Center. O callback a seguir será invocado logo antes de enviar o crash armazenado dos lançamentos anteriores do aplicativo. Ele não será invocado quando o acidente acontecer. Aqui está um exemplo de como anexar texto e uma imagem a um crash:

- (NSArray<MSACErrorAttachmentLog *> *)attachmentsWithCrashes:(MSACCrashes *)crashes
                                             forErrorReport:(MSACErrorReport *)errorReport {
  MSACErrorAttachmentLog *attachment1 = [MSACErrorAttachmentLog attachmentWithText:@"Hello world!" filename:@"hello.txt"];
  MSACErrorAttachmentLog *attachment2 = [MSACErrorAttachmentLog attachmentWithBinary:[@"Fake image" dataUsingEncoding:NSUTF8StringEncoding] filename:@"fake_image.jpeg" contentType:@"image/jpeg"];
  return @[ attachment1, attachment2 ];
}
func attachments(with crashes: Crashes, for errorReport: ErrorReport) -> [ErrorAttachmentLog]? {
  let attachment1 = ErrorAttachmentLog.attachment(withText: "Hello world!", filename: "hello.txt")
  let attachment2 = ErrorAttachmentLog.attachment(withBinary: "Fake image".data(using: String.Encoding.utf8), filename: nil, contentType: "image/jpeg")
  return [attachment1!, attachment2!]
}

Observação

O limite de tamanho atualmente é de 7 MB. A tentativa de enviar um anexo maior disparará um erro.

Habilitar ou desabilitar falhas do App Center no tempo de execução

Você pode habilitar e desabilitar o Crashes no App Center durante o tempo de execução. Se você desabilitá-lo, o SDK não fará nenhum relatório de falha para o aplicativo.

[MSACCrashes setEnabled:NO];
Crashes.enabled = false

Para habilitar o Crashes no App Center novamente, use a mesma API, mas passe YES/true como um parâmetro.

[MSACCrashes setEnabled:YES];
Crashes.enabled = true

O estado é mantido no armazenamento do dispositivo entre as inicializações do aplicativo.

Observação

Esse método só deve ser usado depois que Crashes tiver sido iniciado.

Verificar se o recurso de 'Crashes' do App Center está habilitado

Você também pode verificar se o recurso App Center Crashes está habilitado ou não:

BOOL enabled = [MSACCrashes isEnabled];
var enabled = Crashes.enabled

Observação

Esse método só deve ser usado depois Crashes de iniciado, ele sempre retornará false antes do início.