투케이2K

698. (Android/Java) [유틸 파일] getAppExitReason : getHistoricalProcessExitReasons 사용해 앱 종료 원인 확인 본문

Android

698. (Android/Java) [유틸 파일] getAppExitReason : getHistoricalProcessExitReasons 사용해 앱 종료 원인 확인

투케이2K 2023. 11. 27. 19:15

[개발 환경 설정]

개발 툴 : AndroidStudio

 

[소스 코드]

    // -----------------------------------------------------------------------------------------
    // TODO [SEARCH FAST] : [RETURN] getAppExitReason : 이전 앱 종료 된 원인 확인 수행
    // -----------------------------------------------------------------------------------------
    public static String getAppExitReason(Context mContext, String packageName) {

        /**
         * // -----------------------------------------
         * [getAppExitReason 메소드 설명]
         * // -----------------------------------------
         * 1. 이전 앱 수행 후 종료 된 원인 확인
         * // -----------------------------------------
         * 2. 호출 방식 :
         *
         * C_App.getAppExitReason(A_Intro.this, "com.example.javaproject");
         *
         * // -----------------------------------------
         * 3. 리턴 데이터 : 앱 종료 된 원인 로그 리턴
         *
         *     ProcessName : com.example.javaproject
         *     ProcessId : 19470
         *     ExitDate : 2023-11-27 09:47:25:827
         *     ExitReason : 사용자 요청으로 인해 애플리케이션 프로세스가 종료되었습니다
         *     ExitDescription : stop com.example.javaproject due to from pid 20148
         * // -----------------------------------------
         * 4. TODO 추가 설명 :
         *
         * ActivityManager : 앱 활동, 서비스 및 프로세스에 대한 정보를 제공합니다
         * ActivityManager 는 디버깅 또는 정보 제공 목적으로 사용되며 앱의 런타임 동작에 영향을 주는 데 사용되어서는 안 됩니다
         *
         * // -----------------------------------------
         * 5. 참 고 :
         *
         * https://developer.android.com/reference/android/app/ActivityManager
         * https://developer.android.com/reference/android/app/ApplicationExitInfo
         * // -----------------------------------------
         * */


        // [리턴 값 선언]
        String returnData = "";
        String M_LOG = "";


        // [로직 처리 실시]
        try {

            // [인풋 패키지 명칭 널 체크 수행]
            if (C_Util.stringNotNull(packageName) == true){

                // [ActivityManager 인스턴스 생성]
                ActivityManager manager = (ActivityManager) mContext.getSystemService(ACTIVITY_SERVICE);


                // [앱 종료 로그 획득 실시]
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {

                    // [앱 종료 로그 획득 : getHistoricalProcessExitReasons] : [10 개 지정]
                    List exitList = manager.getHistoricalProcessExitReasons(packageName,0, 10);

                    // [널 체크 수행]
                    if (exitList != null && exitList.size()>0){

                        // [종료 시간 기준으로 정렬]
                        exitList.sort(Comparator.comparing(ApplicationExitInfo::getTimestamp).reversed());

                        // [for 문을 수행하면서 로그 확인]
                        String reason = "";
                        for (int i=0; i<exitList.size(); i++){
                            reason = "\n\n"; // [초기화]

                            // [ApplicationExitInfo 생성]
                            ApplicationExitInfo exitInfo = (ApplicationExitInfo) exitList.get(i);

                            reason += "ProcessName : " + String.valueOf(exitInfo.getProcessName()) + "\n";
                            reason += "ProcessId : " + String.valueOf(exitInfo.getPid()) + "\n";
                            reason += "ExitDate : " + String.valueOf(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(new Date(exitInfo.getTimestamp()))) + "\n";

                            if (exitInfo.getReason() == ApplicationExitInfo.REASON_ANR){
                                reason += "ExitReason : " + "응답이 없어(ANR) 애플리케이션 프로세스가 종료되었습니다" + "\n";
                            }
                            else if (exitInfo.getReason() == ApplicationExitInfo.REASON_CRASH){
                                reason += "ExitReason : " + "소스코드에서 처리되지 않은 예외로 인해 애플리케이션 프로세스가 중단되었습니다" + "\n";
                            }
                            else if (exitInfo.getReason() == ApplicationExitInfo.REASON_CRASH_NATIVE){
                                reason += "ExitReason : " + "네이티브 충돌로 인해 애플리케이션 프로세스가 중단되었습니다" + "\n";
                            }
                            else if (exitInfo.getReason() == ApplicationExitInfo.REASON_DEPENDENCY_DIED){
                                reason += "ExitReason : " + "종속성이 사라져 애플리케이션 프로세스가 종료되었습니다" + "\n";
                            }
                            else if (exitInfo.getReason() == ApplicationExitInfo.REASON_EXCESSIVE_RESOURCE_USAGE){
                                reason += "ExitReason : " + "과도한 리소스 사용으로 인해 시스템에서 응용 프로그램 프로세스가 종료되었습니다" + "\n";
                            }
                            else if (exitInfo.getReason() == ApplicationExitInfo.REASON_EXIT_SELF){
                                reason += "ExitReason : " + "System.exit() 종료 코드 사용으로 프로세스가 종료되었습니다" + "\n";
                            }

                            else if (exitInfo.getReason() == ApplicationExitInfo.REASON_FREEZER){
                                reason += "ExitReason : " + "응용 프로그램 프로세스가 정지된 동안 동기화 바인더 트랜잭션을 수신했기 때문에 App Freezer 에 의해 종료되었습니다" + "\n";
                            }
                            else if (exitInfo.getReason() == ApplicationExitInfo.REASON_INITIALIZATION_FAILURE){
                                reason += "ExitReason : " + "초기화 실패로 인해 애플리케이션 프로세스가 종료되었습니다" + "\n";
                            }
                            else if (exitInfo.getReason() == ApplicationExitInfo.REASON_LOW_MEMORY){
                                reason += "ExitReason : " + "응용 프로그램 프로세스가 시스템 메모리 부족으로 인해 종료되었습니다" + "\n";
                            }
                            else if (exitInfo.getReason() == ApplicationExitInfo.REASON_OTHER){
                                reason += "ExitReason : " + "앱에서 조치를 취할 수 없는 다양한 다른 이유로 인해 시스템에서 애플리케이션 프로세스를 종료했습니다 (ex : 시스템 업데이트)" + "\n";
                            }
                            else if (exitInfo.getReason() == ApplicationExitInfo.REASON_PERMISSION_CHANGE){
                                reason += "ExitReason : " + "런타임 권한 변경으로 인해 애플리케이션 프로세스가 종료되었습니다" + "\n";
                            }
                            else if (exitInfo.getReason() == ApplicationExitInfo.REASON_SIGNALED){
                                reason += "ExitReason : " + "OS 신호의 결과로 인해 애플리케이션 프로세스가 중단되었습니다" + "\n";
                            }
                            else if (exitInfo.getReason() == ApplicationExitInfo.REASON_UNKNOWN){
                                reason += "ExitReason : " + "알 수 없는 이유로 프로세스가 중단되었습니다" + "\n";
                            }
                            else if (exitInfo.getReason() == ApplicationExitInfo.REASON_USER_REQUESTED){
                                reason += "ExitReason : " + "사용자 요청으로 인해 애플리케이션 프로세스가 종료되었습니다" + "\n";
                            }
                            else if (exitInfo.getReason() == ApplicationExitInfo.REASON_USER_STOPPED){
                                reason += "ExitReason : " + "여러 사용자가 있는 장치에서 실행 중인 사용자가 중지되었기 때문에 응용 프로그램 프로세스가 종료되었습니다" + "\n";
                            }
                            else {
                                reason += "ExitReason : " + String.valueOf(exitInfo.getReason()) + "\n";
                            }

                            reason += "ExitDescription : " + String.valueOf(exitInfo.getDescription()) + "\n\n";

                            // ---------------------------------------
                            
                            // [단일 로그 확인 및 리턴]
                            if (i == 0){

                                M_LOG = "[Success] :: Get Exit Reason Check";
                                returnData = reason;
                                break; // [반복문 종료]

                            }

                            // ---------------------------------------

                            // [전체 출력 시 로그]
                            /*
                            S_Log._W_("Get Exit Log [" + String.valueOf(i) + "]", new String[]{
                                    String.valueOf(reason)
                            });
                            // */

                            // ---------------------------------------
                        }

                    }
                    else {
                        M_LOG = "[Error] :: Get exitList Fail :: Reason :: Exit List Is Null";
                    }

                }
                else {
                    M_LOG = "[Error] :: Get exitList Fail :: Reason :: Android Version 11 Low";
                }

            }
            else {
                M_LOG = "[Error] :: Input Data Is Null";
            }

        } catch (Exception e) {
            M_LOG = "[Exception] :: " + String.valueOf(e.getMessage());
            S_Log._printStackTrace_(mContext, S_FinalMsg.LOG_BUG_STATE, null, e);
        }


        // [로그 출력 실시]
        ///*
        // ===============================================================
        S_Log._D_("이전 앱 수행 후 종료 된 원인 확인", new String[]{
                "INPUT :: " + String.valueOf(packageName),
                "M_LOG :: " + String.valueOf(M_LOG),
                "RETURN :: " + String.valueOf(returnData)
        });
        // ===============================================================
        // */


        // [리턴 반환 실시]
        return returnData;
    }
 

[결과 출력]

 

D///===========//: ================================================
I/: [LOG :: CLASS PLACE :: com.example.javaproject.C_App.getAppExitReason(C_App.java:9310)]
I/: ----------------------------------------------------
I/: [LOG :: NOW TIME :: 2023-11-27 09:47:40 월요일]
I/: ----------------------------------------------------
I/: [LOG :: DESCRIPTION :: 이전 앱 수행 후 종료 된 원인 확인]
I/: ----------------------------------------------------
I/: [LOG :: INPUT :: com.example.javaproject]
I/: ----------------------------------------------------
I/: [LOG :: M_LOG :: [Success] :: Get Exit Reason Check]
I/: ----------------------------------------------------
I/: [LOG :: RETURN :: 
    
    ProcessName : com.example.javaproject
    ProcessId : 19470
    ExitDate : 2023-11-27 09:47:25:827
    ExitReason : 사용자 요청으로 인해 애플리케이션 프로세스가 종료되었습니다
    ExitDescription : stop com.example.javaproject due to from pid 20148
    
    ]
D///===========//: ================================================

 

반응형
Comments