Version: 2023.2
언어: 한국어
런타임 권한 요청
Unity Android 애플리케이션 종료

Android 크래시 처리

Android에서 Unity 애플리케이션의 크래시 처리는 크래시 핸들러 체인으로 작동합니다. 체인의 시작 부분에 있는 크래시 핸들러가 먼저 크래시를 수신하여 크래시를 처리하고, 체인의 다음 크래시 핸들러로 크래시를 전달할 수도 있습니다. 체인 내 크래시 핸들러의 순서는 설치된 순서에 따라 정의됩니다. 가장 먼저 설치된 크래시 핸들러가 크래시를 가장 나중에 수신하고, 가장 나중에 설치된 크래시 핸들러가 크래시를 가장 먼저 수신합니다. 기본적으로 Unity는 체인에서 첫 번째 크래시 핸들러 역할을 합니다. 크래시를 처리하여 체인의 다음 크래시 핸들러(기본적으로 Android 시스템 크래시 핸들러)로 전달합니다.

Unity가 크래시에 서로 다르게 반응하도록 설정하고 체인에 자체 커스텀 크래시 핸들러를 추가할 수도 있습니다. 이 페이지에서는 Unity가 크래시를 처리하는 데 사용하는 메서드를 지정하는 방법과 커스텀 크래시 핸들러를 생성하는 방법을 설명합니다.

Unity가 크래시를 처리하는 방법 지정

Unity의 기본 크래시 핸들 동작을 사용하지 않으려는 경우, -androidChainedSignalHandlerBehavior 커맨드 라인 인자를 사용하여 Unity가 크래시에 반응하는 방식을 변경할 수 있습니다. 이 인자는 다음 값 중 하나를 사용합니다.

동작 값 설명
legacy 네이티브 크래시가 발생하면 Unity는 크래시를 Java 예외로 래핑하여 표시합니다. Unity는 설치된 크래시 핸들러나 기본 시스템으로 크래시를 전달하지 않습니다.
참고: 향후 Unity 버전에서는 -androidChainedSignalHandlerBehavior 커맨드 라인 인자가 더 이상 legacy 값을 지원하지 않습니다.
disabled 네이티브 크래시가 발생하면 Unity는 이를 무시하며 Android는 크래시를 체인의 다음 크래시 핸들러로 직접 전달합니다. 이는 커스텀 크래시 핸들러가 설치되어 있는 경우 커스텀 크래시 핸들러이며, 설치되어 있지 않은 경우 기본 시스템입니다.
참고: 이 값을 사용하면 Unity 클라우드 다이그노스틱스와 같은 Unity 서비스는 더 이상 크래시를 처리하고 보고하지 않습니다.

이 커맨드 라인 인자를 Unity에 전달하는 자세한 방법은 Android 플레이어 커맨드 라인 인자 지정을 참조하십시오.

커스텀 크래시 핸들러 생성 및 설정

이 섹션에는 자체 크래시 핸들러를 생성하고 설정하는 방법에 대한 예제가 포함되어 있습니다. 이를 사용하려면 Unity의 레거시 크래시 처리 동작을 사용하지 않아야 합니다. 자세한 내용은 Unity가 크래시를 처리하는 방법 지정을 참조하십시오.

크래시 핸들러 생성

다음 코드 샘플은 커스텀 크래시 핸들러를 보여 줍니다. IL2CPP 스크립팅 백엔드를 사용하는 경우, 이 예제 cpp 파일을 Unity 프로젝트에 바로 배치할 수 있습니다. Unity는 이를 libil2cpp.cpp의 일부로 컴파일합니다. Mono 스크립팅 백엔드를 사용하는 경우, 자체 공유 라이브러리를 컴파일하고 연결해야 합니다. 자세한 내용은 Android용 네이티브 플러그인 만들기를 참조하십시오.

android_crash_handler.cpp

# include <android/log.h>
# include <jni.h>
# include <signal.h>

struct sigaction s_PreviousHandler;
bool s_SignalHandlerInstalled;

static void MyCustomHandler(int sig, siginfo_t* info, void* ucontext)
{
  __android_log_print(ANDROID_LOG_VERBOSE, "CustomCrashHandler", "Handling signal %d", sig);
  s_PreviousHandler.sa_sigaction(sig, info, ucontext);
}

extern "C" void InstallCustomSignalHandlers()
{
  struct sigaction Action = {};
  Action.sa_sigaction = MyCustomHandler;
  // Note: Register more signals if you want.
  Action.sa_flags = SIGSEGV;
  sigaction(SIGSEGV, &Action, &s_PreviousHandler);
  s_SignalHandlerInstalled = true;
}

extern "C" JNIEXPORT void Java_com_unity3d_player_UnityPlayerActivity_InstallCustomSignalHandlersFromJava()
{
  InstallCustomSignalHandlers();
}

extern "C" void UninstallCustomSignalHandlers()
{
  if (s_SignalHandlerInstalled)
  {
      sigaction(SIGSEGV, &s_PreviousHandler, nullptr);
      s_SignalHandlerInstalled = false;
  }
}

크래시 핸들러 설치

크래시 핸들러를 설치하고 Unity가 이를 크래시 처리에 사용하도록 하려면 위 cpp 파일에 있는 InstallCustomSignalHandlers 메서드를 호출합니다. C# 또는 Java 코드를 사용하여 수행할 수 있지만, Java를 통해 이 메서드를 호출하는 것이 가장 좋습니다. Unity 플레이어가 초기화되고 나서 C# 코드가 실행되기 전에 크래시가 발생할 수 있기 때문입니다.

다음 코드 예제는 Java 코드를 통해 InstallCustomSignalHandlers 메서드를 호출하는 방법을 보여 줍니다. 이를 프로젝트에 추가하려면 Java 파일을 플러그인으로 설치(Java 또는 Kotlin 소스 플러그인 참조)하거나 익스포트한 프로젝트에서 기존 Java 파일을 수정할 수 있습니다.

참고: 이 메서드를 어디에서 호출하는지에 따라 크래시 처리의 동작이 변경됩니다. Unity 런타임 초기화 전에 호출하는 경우, 즉 mUnityPlayer = new UnityPlayer(this, this);가 포함된 코드 줄을 호출하면 네이티브 크래시 발생 시 Unity의 크래시 핸들러가 먼저 실행된 후 시그널 핸들러가 실행됩니다(Unity가 시그널을 전달할 경우). Unity 런타임 초기화 후에 InstallCustomSignalHandlers를 호출하는 경우 네이티브 크래시 발생 시 핸들러가 먼저 실행되며, 시그널을 전달하는 것은 사용자의 책임입니다.

UnityPlayerActivity.java

...
  public native void InstallCustomSignalHandlersFromJava();
  static
  {
      System.loadLibrary("il2cpp");
  }
  // Setup activity layout
  @Override protected void onCreate(Bundle savedInstanceState)
  {
      InstallCustomSignalHandlersFromJava();
      ...
      mUnityPlayer = new UnityPlayer(this, this);
      setContentView(mUnityPlayer);
      mUnityPlayer.requestFocus();
  }
...
런타임 권한 요청
Unity Android 애플리케이션 종료