일모도원(日暮途遠) 개발자
[안드로이드개발] 릴리즈 모드에서만 죽는 현상 proguard관련 본문
챗GPT API를 쓰는 앱을 개발중에 릴리즈모드에서만 죽는 현상이 발견되었다.
에러로그가 이렇게 알아보기 힘들게 나온다. 다행히 ".NoSuchFieldException: system"라는 문구로 어디가 문제인지는 파악이 된다.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.dalnimsoft.araconv, PID: 17238
java.lang.AssertionError: java.lang.NoSuchFieldException: system
at f.h.g.r.k.n$j0.<init>(:792)
at f.h.g.r.k.n$w.a(:818)
at f.h.g.d.k(:458)
at f.h.g.r.k.i.b(:117)
at f.h.g.r.k.i.e(:166)
at f.h.g.r.k.i.a(:102)
at f.h.g.d.k(:458)
at f.h.g.r.k.b.a(:53)
at f.h.g.d.k(:458)
at f.h.g.r.k.i.b(:117)
at f.h.g.r.k.i.e(:166)
at f.h.g.r.k.i.a(:102)
at f.h.g.d.k(:458)
at retrofit2.converter.gson.GsonConverterFactory.requestBodyConverter(:70)
at retrofit2.Retrofit.nextRequestBodyConverter(:315)
로그가 저렇게 나오는 이유가 결국 에러원인과도 관련이 있다.
proguard-rules.pro에 정의 된대로 obfuscate를 하는데, obfuscate라는 말 그대로 리버스 엔지니어링 할때 혼동스럽게 하기 위해서 클래스명 필드명들을 전부 a, b 이런씩으로 확 줄여버린다. (또한 조금이나마 용량이 줄어들기도 한다. 글자수를 줄이니까)
buildTypes {
release {
debuggable false
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.config
manifestPlaceholders = [crashlyticsEnabled: true]
ndk {
debugSymbolLevel 'FULL'
}
}
}
만약 proguard를 적용안시키고 테스트해볼려고 하면 그냥 minifyEnabled와 shrinkResources를 false로 두고 테스트 하면 된다.
문제가 된 코드는 여기다.
ChatGPTRequest 클래스 안데 Message라는 클래스가 있고 그안에 다시 Role이라는 enum이 있는데 여기에 있는 system이 축약이 되어서 문제가 되었다. (근데 이게 왜 크래쉬인지는 모르겠다. API호출이 실패하면 되는거 같은데...)
public class ChatGPTRequest {
public static class Message {
public enum Role {
system,
user,
assistant
}
}
}
그리고 이부분에서도 에러가 났다. 아마 @SerializedName("object")도 "object"를 a 이런씩으로 줄여버린거 같다.
public class ChatCompletionResponse {
@SerializedName("id")
private String id;
@SerializedName("object")
private String object;
public static class Choice {
@SerializedName("message")
private Message message;
}
public static class Message {
@SerializedName("role")
private String role;
@SerializedName("content")
private String content;
}
그래서 proguard-rules.pro에 아래를 추가해서 해결했다.
즉 아래 클래스에 있는것 obfuscate하지 말고 그냥 두라는거다.
주의할점은 부모 클래스만 하지 말고 내부 클래스와 열거형(enum)도 같이 적어줘야 한다.
-keepclassmembers class com.dalread.network.ChatCompletionResponse { *; }
-keepclassmembers class com.dalread.network.ChatCompletionResponse$Message { *; }
-keepclassmembers class com.dalread.network.ChatCompletionResponse$Choice { *; }
-keepclassmembers class com.dalread.network.ChatCompletionResponse$Usage { *; }
-keepclassmembers class com.dalread.network.ChatGPTRequest { *; }
-keepclassmembers class com.dalread.network.ChatGPTRequest$Message { *; }
-keepclassmembers class com.dalread.network.ChatGPTRequest$Message$Role { *; }
내부 클래스와 열거형(enum)을 일일히 적기 귀찮으면 아래처럼 $*를 클래스에 추가하면 된다.
-keepclassmembers class com.dalread.network.ChatCompletionResponse$* { *; }
-keepclassmembers class com.dalread.network.ChatGPTRequest$* { *; }
참고로 -keep을 써도 되는데 -keep은 클래스명도 축약하지 말라는 뜻이다. 내 경우에는 클래스명은 축약해도 되니까 -keppclassmembers를 써서 클래스 멤버들만 축약하지 말고 keep하라는 명령을 사용해서 해결했다.
'안드로이드 개발 > 안드로이드' 카테고리의 다른 글
[안드로이드 개발] 아직도 헷갈리는 안드로이드 폴더 구조. (0) | 2023.04.07 |
---|---|
[안드로이드UI] 채팅 대화내역 키보드에 안가리게 하기. (0) | 2023.04.01 |
[안드로이드 개발] retrofit으로 텍스트 받아오기. (0) | 2023.03.09 |
[Android] 웹브라우저에서 텍스트 선택후 앱 열기 (0) | 2023.02.13 |
[Android] 텍스트 꾸미기 (Span) (0) | 2022.12.29 |