다음을 통해 공유


App Center 충돌(Android)

중요

Visual Studio App Center는 2025년 3월 31일에 사용 중지될 예정입니다. Visual Studio App Center가 완전히 사용 중지될 때까지 계속 사용할 수 있지만 마이그레이션을 고려할 수 있는 몇 가지 권장 대안이 있습니다.

지원 타임라인 및 대안에 대해 자세히 알아봅니다.

App Center 충돌은 앱이 충돌할 때마다 자동으로 크래시 로그를 생성합니다. 로그는 먼저 디바이스의 스토리지에 기록되며 사용자가 앱을 다시 시작하면 크래시 보고서가 App Center로 전송됩니다. 크래시 수집은 베타 및 라이브 앱( 즉, Google Play에 제출된 앱)에서 모두 작동합니다. 크래시 로그에는 크래시 문제를 해결하는 데 도움이 되는 중요한 정보가 포함되어 있습니다.

애플리케이션에서 SDK를 아직 설정하지 않은 경우 시작 섹션을 따릅니다.

테스트 크래시 생성

App Center Crashs는 SDK를 쉽게 테스트하기 위한 테스트 크래시를 생성하는 API를 제공합니다. 이 API는 디버그 빌드에서만 사용할 수 있으며 릴리스 빌드에서는 아무 작업도 수행하지 않습니다.

Crashes.generateTestCrash();
Crashes.generateTestCrash()

이전 충돌에 대한 자세한 정보 가져오기

App Center Crashs에는 앱이 충돌하는 경우 추가 정보를 제공하는 두 개의 API가 있습니다.

앱이 이전 세션에서 메모리 부족 경고를 받았나요?

SDK를 시작한 후 언제든지 앱이 이전 세션에서 메모리 경고를 수신했는지 검사 수 있습니다.

Crashes.hasReceivedMemoryWarningInLastSession();
Crashes.hasReceivedMemoryWarningInLastSession()

이 API는 비동기입니다. 자세한 내용은 App Center 비동기 API 가이드에서 확인할 수 있습니다.

참고

이 메서드는 시작된 후에 Crashes 만 사용해야 하며, 시작 전에 항상 반환 false 됩니다.

참고

경우에 따라 메모리가 낮은 디바이스에서 이벤트를 보낼 수 없습니다.

이전 세션에서 앱이 충돌했나요?

SDK를 시작한 후 언제든지 이전 실행에서 앱이 충돌했는지 검사 수 있습니다.

Crashes.hasCrashedInLastSession();
Crashes.hasCrashedInLastSession()

이 API는 비동기입니다. 자세한 내용은 App Center 비동기 API 가이드에서 확인할 수 있습니다.

이는 크래시가 발생한 후 앱의 동작 또는 UI를 조정하려는 경우에 유용합니다. 일부 개발자는 사용자에게 사과하기 위해 추가 UI를 표시하거나 충돌이 발생한 후 연락할 방법을 원합니다.

참고

이 메서드는 시작된 후에 Crashes 만 사용해야 하며, 시작 전에 항상 반환 false 됩니다.

마지막 충돌에 대한 세부 정보

앱이 이전에 충돌한 경우 마지막 충돌에 대한 세부 정보를 얻을 수 있습니다.

Crashes.getLastSessionCrashReport();
Crashes.getLastSessionCrashReport()

이 API는 비동기입니다. 자세한 내용은 App Center 비동기 API 가이드에서 확인할 수 있습니다.

이 API에는 다양한 사용 사례가 있으며, 가장 일반적인 사용 사례는 이 API를 호출하고 사용자 지정 CrashesListener를 구현하는 사용자입니다.

참고

이 메서드는 시작된 후에 Crashes 만 사용해야 하며, 시작 전에 항상 반환 null 됩니다.

App Center 크래시 사용 사용자 지정

App Center 충돌은 개발자가 App Center에 크래시 로그를 보내기 전과 전송할 때 추가 작업을 수행할 수 있는 콜백을 제공합니다.

콜백을 처리하려면 인터페이스의 모든 메서드를 CrashesListener 구현하거나 클래스를 AbstractCrashesListener 재정의하고 관심 있는 메서드만 선택합니다.

사용자 고유의 CrashesListener 사용

사용자 고유의 CrashesListener를 만들고 다음과 같이 할당합니다.

CrashesListener customListener = new CrashesListener() {
    // Implement all callbacks here.
};
Crashes.setListener(customListener);
val customListener = object : CrashesListener {
    // Implement all callbacks here.
}
Crashes.setListener(customListener)

일부 콜백을 사용자 지정하는 데만 관심이 있는 경우 대신 를 AbstractCrashesListener 사용합니다.

AbstractCrashesListener customListener = new AbstractCrashesListener() {
    // Implement any callback here as required.
};
Crashes.setListener(customListener);
val customListener = object : AbstractCrashesListener() {
    // Implement any callback here as required.
}
Crashes.setListener(customListener)

참고

App Center가 시작 직후 크래시 처리를 시작하기 때문에 를 호출AppCenter.start()하기 전에 수신기를 설정합니다.

크래시가 처리되어야 하나요?

특정 크래시가 처리되어야 하는지 여부를 결정하려는 경우 이 콜백을 구현합니다. 예를 들어 무시하려는 시스템 수준 크래시가 있을 수 있으며 App Center로 보내지 않을 수 있습니다.

@Override
public boolean shouldProcess(ErrorReport report) {
    return true; // return true if the crash report should be processed, otherwise false.
}
override fun shouldProcess(report: ErrorReport?): Boolean {
    return true
}

사용자 개인 정보 보호가 중요한 경우 App Center에 크래시 보고서를 보내기 전에 사용자 확인을 받을 수 있습니다. SDK는 크래시 보고서를 보내기 전에 사용자 확인을 기다리도록 App Center Crashs에 지시하는 콜백을 노출합니다.

이렇게 하기로 선택한 경우 사용자의 확인(예: 항상 보내기, 보내기보내지 않음) 옵션 중 하나가 포함된 대화 상자 프롬프트를 통해 사용자의 확인을 받을 책임이 있습니다. 입력에 따라 App Center에서 수행할 작업을 알려 주며 그에 따라 크래시가 처리됩니다.

참고

SDK는 이에 대한 대화 상자를 표시하지 않습니다. 앱은 사용자 동의를 요청하는 자체 UI를 제공해야 합니다.

다음 콜백은 충돌을 보내기 전에 사용자 확인을 기다리도록 SDK에 지시하는 방법을 보여 줍니다.

@Override
public boolean shouldAwaitUserConfirmation() {

    // Build your own UI to ask for user consent here. SDK doesn't provide one by default.

    // Return true if you built a UI for user consent and are waiting for user input on that custom UI, otherwise false.
    return true;
}
override fun shouldAwaitUserConfirmation(): Boolean {
    return true
}

를 반환 true하는 경우 앱은 사용자의 권한을 획득(사용자 고유의 코드 사용)하고 다음 API를 사용하여 결과와 함께 SDK에 메시지를 보내야 합니다.

// Depending on the user's choice, call Crashes.notifyUserConfirmation() with the right value.
Crashes.notifyUserConfirmation(Crashes.DONT_SEND);
Crashes.notifyUserConfirmation(Crashes.SEND);
Crashes.notifyUserConfirmation(Crashes.ALWAYS_SEND);
Crashes.notifyUserConfirmation(Crashes.DONT_SEND)
Crashes.notifyUserConfirmation(Crashes.SEND)
Crashes.notifyUserConfirmation(Crashes.ALWAYS_SEND)

예를 들어 사용자 지정 대화 상자 예제를 참조할 수 있습니다.

크래시 로그에 대한 전송 상태 대한 정보 가져오기

때때로 앱 충돌의 상태 알고 싶을 수 있습니다. 일반적인 사용 사례는 앱이 충돌 보고서를 제출하고 있음을 사용자에게 알리는 UI를 표시하거나, 실행 후 앱이 빠르게 충돌하는 경우 크래시 로그를 제출할 수 있도록 앱의 동작을 조정하려고 할 수 있다는 것입니다. App Center 크래시의 세 가지 콜백이 있습니다. 이 콜백은 앱에서 사용 중임을 알리기 위해 사용할 수 있습니다.

다음 콜백은 SDK가 크래시 로그를 보내기 전에 호출됩니다.

@Override
public void onBeforeSending(ErrorReport errorReport) {
    // Your code, e.g. to present a custom UI.
}
override fun onBeforeSending(report: ErrorReport?) {
    // Your code, e.g. to present a custom UI.
}

엔드포인트에 네트워크 문제 또는 중단이 있고 앱을 onBeforeSending 다시 시작하는 경우 프로세스가 다시 시작되면 가 다시 트리거됩니다.

다음 콜백은 SDK가 크래시 로그를 성공적으로 보낸 후에 호출됩니다.

@Override
public void onSendingSucceeded(ErrorReport report) {
    // Your code, e.g. to hide the custom UI.
}
override fun onSendingSucceeded(report: ErrorReport?) {
    // Your code, e.g. to hide the custom UI.
}

SDK가 크래시 로그를 보내지 못한 경우 다음 콜백이 호출됩니다.

@Override
public void onSendingFailed(ErrorReport report, Exception e) {
    // Your code goes here.
}
override fun onSendingFailed(report: ErrorReport?, e: Exception?) {
    // Your code goes here.
}

수신은 onSendingFailed4xx 코드와 같은 복구할 수 없는 오류가 발생했음을 의미합니다. 예를 들어 401 은 가 잘못됨을 appSecret 의미합니다.

이 콜백은 네트워크 문제인 경우 트리거되지 않습니다. 이 경우 SDK는 계속 재시도하고 네트워크 연결이 중단되는 동안 다시 시도를 일시 중지합니다.

크래시 보고서에 첨부 파일 추가

크래시 보고서에 이진 및 텍스트 첨부 파일을 추가할 수 있습니다. SDK는 충돌과 함께 전송되므로 App Center 포털에서 볼 수 있습니다. 다음 콜백은 이전 애플리케이션 시작에서 저장된 크래시 보내기 직전에 호출됩니다. 충돌이 발생하면 호출되지 않습니다. 첨부 파일 이름은 미니덤프 파일에 예약되어 있으므로 이름이 지정 minidump.dmp되지 않았는지 확인합니다. 다음은 충돌 시 텍스트와 이미지를 연결하는 방법의 예입니다.

@Override
public Iterable<ErrorAttachmentLog> getErrorAttachments(ErrorReport report) {

    // Attach some text.
    ErrorAttachmentLog textLog = ErrorAttachmentLog.attachmentWithText("This is a text attachment.", "text.txt");

    // Attach binary data.
    byte[] binaryData = getYourBinary();
    ErrorAttachmentLog binaryLog = ErrorAttachmentLog.attachmentWithBinary(binaryData, "your_filename.jpeg", "image/jpeg");

    // Return attachments as list.
    return Arrays.asList(textLog, binaryLog);
}
override fun getErrorAttachments(report: ErrorReport?): MutableIterable<ErrorAttachmentLog> {

    // Attach some text.
    val textLog = ErrorAttachmentLog.attachmentWithText("This is a text attachment.", "text.txt")

    // Attach binary data.
    val binaryData = getYourBinary()
    val binaryLog = ErrorAttachmentLog.attachmentWithBinary(binaryData, "your_filename.jpeg", "image/jpeg")

    // Return attachments as list.
    return listOf(textLog, binaryLog)
}

참고

크기 제한은 현재 7MB입니다. 더 큰 첨부 파일을 보내려고 하면 오류가 트리거됩니다.

런타임에 App Center 충돌 사용 또는 사용 안 함

런타임에 App Center 크래시를 사용하도록 설정하고 사용하지 않도록 설정할 수 있습니다. 사용하지 않도록 설정하면 SDK는 앱에 대한 크래시 보고를 수행하지 않습니다.

Crashes.setEnabled(false);
Crashes.setEnabled(false)

App Center 크래시를 다시 사용하도록 설정하려면 동일한 API를 사용하지만 매개 변수로 전달 true 합니다.

Crashes.setEnabled(true);
Crashes.setEnabled(true)

상태는 애플리케이션이 시작될 때 디바이스의 스토리지에 유지됩니다.

이 API는 비동기입니다. 자세한 내용은 App Center 비동기 API 가이드에서 확인할 수 있습니다.

참고

이 메서드는 시작된 후에 Crashes 만 사용해야 합니다.

App Center 크래시가 사용하도록 설정되어 있는지 확인

App Center 크래시가 사용하도록 설정되어 있는지 여부를 검사 수도 있습니다.

Crashes.isEnabled();
Crashes.isEnabled()

이 API는 비동기입니다. 자세한 내용은 App Center 비동기 API 가이드에서 확인할 수 있습니다.

참고

이 메서드는 시작된 후에 Crashes 만 사용해야 하며, 시작 전에 항상 반환 false 됩니다.

처리된 오류

App Center를 사용하면 처리된 예외를 사용하여 오류를 추적할 수도 있습니다. 이렇게 하려면 메서드를 사용합니다.trackError

try {
    // your code goes here.
} catch (Exception exception) {
    Crashes.trackError(exception);
}
try {
    // your code goes here.
} catch (exception: Exception) {
    Crashes.trackError(exception)
}

앱은 필요에 따라 처리된 오류 보고서에 속성을 연결하여 추가 컨텍스트를 제공할 수 있습니다. 아래 예제와 같이 속성을 키/값 쌍(문자열에만 해당)의 맵으로 전달합니다.

try {
    // your code goes here.
} catch (Exception exception) {
    Map<String, String> properties = new HashMap<String, String>() {{
        put("Category", "Music");
        put("Wifi", "On");
    }};
    Crashes.trackError(exception, properties, null);
}
try {
    // your code goes here.
} catch (exception: Exception) {
    val properties = mapOf("Category" to "Music", "Wifi" to "On")
    Crashes.trackError(exception, properties, null)
}

필요에 따라 처리된 오류 보고서에 이진 및 텍스트 첨부 파일을 추가할 수도 있습니다. 아래 예제와 같이 첨부 파일을 로 Iterable 전달합니다.

try {
    // your code goes here.
} catch (Exception exception) {

    // Attach some text.
    ErrorAttachmentLog textLog = ErrorAttachmentLog.attachmentWithText("This is a text attachment.", "text.txt");

    // Attach binary data.
    byte[] binaryData = getYourBinary();
    ErrorAttachmentLog binaryLog = ErrorAttachmentLog.attachmentWithBinary(binaryData, "your_filename.jpeg", "image/jpeg");

    // Track an exception with attachments.
    Crashes.trackError(exception, null, Arrays.asList(textLog, binaryLog));
}
try {
    // your code goes here.
} catch (exception: Exception) {

    // Attach some text.
    val textLog = ErrorAttachmentLog.attachmentWithText("This is a text attachment.", "text.txt")

    // Attach binary data.
    val binaryData = getYourBinary()
    val binaryLog = ErrorAttachmentLog.attachmentWithBinary(binaryData, "your_filename.jpeg", "image/jpeg")

    // Track an exception with attachments.
    Crashes.trackError(exception, null, listOf(textLog, binaryLog))
}

NDK 충돌 보고

작동 중단 보고

App Center에서 적절한 크래시 보고서를 받으려면 먼저 위에 나열된 지침에 따라 App Center 크래시 SDK를 설정했는지 확인합니다.

중단 패드 라이브러리 빌드

다음으로, Android 추가 정보용 공식 Google Breakpad에 나열된 지침에 따라 Google Breakpad를 포함하고 컴파일합니다.

참고

App Center SDK는 기본적으로 Google Breakpad를 번들로 묶지 않습니다.

예외 처리기 연결

Google Breakpad가 포함되어 있으면 다음에 NDK 크래시 처리기를 AppCenter.start연결합니다.

// Attach NDK Crash Handler after SDK is initialized.
Crashes.getMinidumpDirectory().thenAccept(new AppCenterConsumer<String>() {
    @Override
    public void accept(String path) {

        // Path is null when Crashes is disabled.
        if (path != null) {
            setupNativeCrashesListener(path);
        }
    }
});

메서드 setupNativeCrashesListener 는 C/C++에서 구현해야 하는 네이티브 메서드입니다.

#include "google-breakpad/src/client/linux/handler/exception_handler.h"
#include "google-breakpad/src/client/linux/handler/minidump_descriptor.h"

void Java_com_microsoft_your_package_YourActivity_setupNativeCrashesListener(
        JNIEnv *env, jobject, jstring path) {
    const char *dumpPath = (char *) env->GetStringUTFChars(path, NULL);
    google_breakpad::MinidumpDescriptor descriptor(dumpPath);
    new google_breakpad::ExceptionHandler(descriptor, NULL, dumpCallback, NULL, true, -1);
    env->ReleaseStringUTFChars(path, dumpPath);
}

문제 해결에 사용되는 위치 dumpCallback :

/*
 * Triggered automatically after an attempt to write a minidump file to the breakpad folder.
 */
bool dumpCallback(const google_breakpad::MinidumpDescriptor &descriptor,
                  void *context,
                  bool succeeded) {

    // Allow system to log the native stack trace.
    __android_log_print(ANDROID_LOG_INFO, "YourLogTag",
                        "Wrote breakpad minidump at %s succeeded=%d\n", descriptor.path(),
                        succeeded);
    return false;
}

이러한 메서드가 제대로 설정되면 앱은 다시 시작 시 자동으로 미니덤프를 App Center로 보냅니다. 문제를 해결하려면 자세한 정보 표시 로그(이전AppCenter.start)AppCenter.setLogLevel(Log.VERBOSE)를 사용하여 앱을 다시 시작한 후 미니덤프가 전송되는 경우 검사 수 있습니다.

참고

App Center는 미니덤프 첨부 파일에 예약된 이름을 minidump.dmp 사용합니다. 제대로 처리할 수 있도록 미니덤프 파일이 아니면 첨부 파일에 다른 이름을 지정해야 합니다.

참고

x86 에뮬레이터에서 충돌을 캡처할 수 없는 알려진 버그가 중단 패드에 있습니다.

기호화

크래시 처리에 대한 자세한 내용은 진단 설명서를 참조하세요.