안드로이드 aar 트러블슈팅 기록
너무 많은 시간을 허비했다.
오랜 삽질 끝에 해결은 했는데 도대체 뭐가 문제였는지도 잘 모르겠다.
일단 기록해놓지 않으면 나중에 기억나지 않을 것이기에 기록한다.
1. 1차 시도
일단 기존 쓰고 있는 앱 소스코드를 기반으로, 새로운 2개의 앱을 만들어내는게 핵심과제였다.
그런데 새로운 앱 2개에서는 만들어내자 기존에 잘 돌던 코드가 동작하지 않았다.
앱 위변조검증이라는 기능이었는데, 타 업체의 라이브러리에 의존하는 코드였다.
타업체가 만든 라이브러리는 2.1.7.jar 라는 파일을 쓰고 있었다.
알고보니 이 라이브러리는 안드로이드 앱의 패키지명이 변경되면 동작하지 않는 방식이었다.
정확히 표현하면 build.gradle 의 applicationId 값이 바뀌면 라이선스 어쩌구 하는 못보던 오류 메시지가 발생했다.
정식 라이선스 값이라는 String 변수가 있고, 해당 변수가 패키지명과 매칭되지 않으면 동작하지 못하도록 제어하는 것 같았다.
이것을 알아내는 데에도 엄청난 시간이 걸렸다(잘 동작하는 AS-IS 프로젝트를 갖다 놓고, TO-BE와 같아지도록 한 줄씩 수정하면서 언제 라이선스 어쩌구 오류 메시지가 발생하는지 테스트했다).
아무튼 패키지명에 알맞게 2개의 정식 라이선스 값을 받아내면 된다고 생각했는데, 새로운 버전의 라이브러리로 교체하라는 답변을 업체로부터 받았다.
새로운 버전의 라이브러리는 라이선스 값과 무관하게 잘 동작한다고 했다.
2. 2차 시도
새로운 버전의 라이브러리는 jar 파일이 아니고 aar 파일이었다.
검색을 동원해본 결과 aar 파일을 프로젝트에 적용하는 방법은 2가지가 있다.
첫번째는 libs 폴더에 aar 파일을 넣고, build.gradle 파일을 수정하는 것이다. 이것에 대해서는 https://blog.naver.com/bb_/221758376358 포스트에 정리해둔 바 있다.
결과적으로 이 방법으로 성공했다.
두번째 방법은 aar을 사용하고 있는 모듈을 추가하는 것이다.
예제로 받은 샘플 프로젝트가 이 방식을 사용하고 있어서 계속 시도해본 방법이다.
결과적으로 이 방법은 실패했지만 방법만 적어둔다.
(1) File – New – Import Module – 모듈 폴더를 선택.
개인적으로는 받은 샘플 프로젝트 안에 aar을 사용하는 모듈이 들어있어서, 해당 폴더를 그대로 복사해왔다. 폴더명은 library_name_v4.0.0 이었다.
(2) build.gradle 파일에 implementation project(path: ‘:library_name_v4.0.0’) 추가
(3) settings.gradle 파일에 include ‘:library_name_v4.0.0’ 추가
처음에는 두번째 방법(aar을 사용하고 있는 모듈을 추가)을 시도했는데, 계속 실패했다.
계속 실패했다는 것은 뭔가 잘못된 것 같으면 전체 롤백하고 처음부터 다시 하기를 반복했다는 뜻이다.
기존에 쓰던 2.1.7.jar 파일을 삭제하고, library_name_v4.0.0 모듈을 추가하고, 빨간줄이 발생한(오류가 발생한) 코드를 고치는 작업이었는데 고칠게 너무 많았다.
기존에 com.업체명~ 으로 시작했던 것들이 모두 net.업체명~ 식으로 패키지명이 바뀌었다.
또 사용하던 메서드들이 없어진 것들이 많아서 코드를 마구 삭제하다가, 너무 많이 건드린 것 같으면 롤백하기를 반복하였다.
결국 작업은 완료되었는데, 이제 앱이 죽는 현상이 생겼다.
한참 원인을 찾지 못하다가 로그캣을 보게 됐다.
——— beginning of crash 라고 해서 익셉션이 나와있었고, FATAL EXCEPTION 이 발생한 것이었다.
핵심이 되는 오류는 java.lang.VerifyError 였다.
|
Caused by: java.lang.VerifyError: Verifier rejected class com.타업체패키지명.타업체클래스명: void com.타업체패키지명.타업체클래스명<init>(boolean) failed to verify: void com.타업체패키지명.타업체클래스명<init>(boolean): [0x31] Expected initialization on uninitialized reference Precise Reference: java.lang.String (declaration of ‘com.타업체패키지명.타업체클래스명’ appears in /data/app/com.자사패키지명-1/split_lib_slice_9_apk.apk) |
막막해서 지인들에게 도움을 요청해보니 검색하여 아래 답변을 주었다.
생각해보면 나도 검색해서 얻을 수 있는 정보였는데 찾지 못한 이유는, 하필 라이브러리에서 오류가 나는 해당 메서드 명이 verify여서 이게 자바 레벨의 오류가 아니라 특정 업체 라이브러리에서만 발생하는 특수한 오류라고 생각했다. 나는 VerifyError 라는 키워드만 빼고 나머지 키워드들로 검색을 하고 있었다…
|
VerifyError 발생 원인 1. 컴파일 시 사용한 라이브러리와 런타임 시 사용한 라이브러리 버전이 달라서 메서드 형태가 다른 경우 2. 사용한 라이브러리가 상위 버전의 JDK 에서 컴파일 된 경우 결국 라이브러리 버전을 맞춰야 한다. |
저기 분명 라이브러리 버전을 맞춰야 한다고 했는데, 나는 어쩐 일인지 JDK버전 내지는 안드로이드 SDK 버전을 맞춰야 한다는 생각이 들었다.
뭐가 뭔지 모르겠는 상태에서 library_name_v4.0.0.aar 을 반디집으로 열어서 AndroidManifest.xml 을 열어보니 안드로이드 버전 29로 되어있었다.
내 프로젝트는 안드로이드 버전 28 이었는데, 어쩐 일인지 build.gradle을 29로 고치면 앱이 동작하지 않았다.
검색을 거듭한 결과 안드로이드 스튜디오 버전 4.0 이상에서 안드로이드 버전 29를 쓸 수 있다는 내용을 보았다.
내가 사용한 안드로이드 스튜디오는 버전 3.4 였다.
확실한지는 모르지만 지푸라기라도 잡는 심정으로 안드로이드 스튜디오 4.0을 깔고, 작업중인 프로젝트를 로드했다.
결과적으로 안드로이드 스튜디오 4.0 에서는 VerifyError 가 발생하지 않았다.
버전을 29로 올리지도 않았다.
그냥 내 프로젝트는 여전히 버전 28이고, aar 은 버전 29였다.
돌이켜보면 샘플 프로젝트도 3점대 안드로이드 스튜디오에서는 빨간줄이 그어져 빌드가 안됐고, 안드로이드 스튜디오 4.0 에서는 잘 열리고 빌드가 됐다.
뇌피셜이지만 해결된 이유는 aar 모듈이 안드로이드 스튜디오 4에서 만들어진 모듈이라서, 그걸 사용하는 프로젝트 역시 안드로이드 스튜디오 4에서 빌드해야 되는 것 같다.
문제는 이렇게 오류는 해결이 됐는데 앱위변조 검증이 통과가 됐다.
통과가 안되어야 정상인데 통과가 됐다.
이게 말이 안되는게 서버쪽에 앱의 고유 해시값이 있을건데 내가 이것저것 고쳤기 때문에, 서버에 올라가 있는 앱의 해시값과 내 앱의 해시값은 전혀 다를 것이란 말이다.
나중에 언급하겠지만 이 때는 verify 를 SimpleVerify 로 고쳐도 똑같이 위변조 검증이 통과됐다.
아무튼 오류는 발생하지 않으나 라이브러리가 똑바로 동작하지 않으니 모두 롤백했다.
=> 나중에 알게된 사실인데 이때 이미 성공을 한 것이었다.
앱위변조 검증은 서버에 따로 앱을 업로드해서 해시값을 만드는게 아니라, 첫번째로 앱위변조 요청(verify 메서드)을 했을 경우 해시값을 서버에 저장하고 그 값을 기준으로 검증하는 것이었다.
3. 3차 시도
2차 시도는 어제인 토요일 얘기고, 일요일인 오늘은 3차 시도였다.
처음부터 안드로이드 스튜디오 4.0 에서 프로젝트를 열어서 빌드를 하고 시작했다.
업체로부터 받은 aar 버전이 2가지가 있었는데, 하나가 어제 시도한 library_name_v4.0.0.aar 이었다.
사실 이것은 또 다른 업체로부터 받았으니 간접적으로 받은 파일에 해당한다.
다른 하나가 library_name_v4.0.4.aar 이었다.
이건 직접적으로 전달받은 거였다.
기존 버전의 버전 갭이 클수록 고쳐야할게 많다는 생각에 4.0.0을 먼저 시도한 것인데, 어제 잘 동작하지 않았으니 또 다시 지푸라기라도 잡는 심정으로 4.0.4 로 시작했다.
aar 을 추가할 때 모듈을 추가하는 방식을 사용하지 않고, 그냥 libs 폴더 안에 aar 파일을 넣는 방식을 사용했다.
그리고 기존 라이브러리(jar)를 지우고 진행을 하는데 아래 오류가 발생했다.
|
execution failed for task ‘:app:transformdexarchivewithexternallibsdexmergerfordebug’. |
뭔가를 잘못했나 싶어서 롤백을 하고 다시 진행해도 똑같은 오류가 발생했다.
검색 결과 가장 도움이 된 포스트는 이것이다. https://miraclehwan.tistory.com/22
|
사용하는 라이브러리마다 참조하는 라이브러리 버전이 다 다를 경우, 메소드의 수가 계속 증가하여 64k개 이상을 가질 경우 위와 같은 에러가 발생한다. (중략) 확실한 해결 방법은 버전이 다른 라이브러리를 사용할 경우 하나로 고정시키는 방법이다. |
로그캣이었는지 디버그 콘솔이었는지 읽을 수 있는 것은 뭐든 꼼꼼히 읽어보니 못보던 패키지명이 있었다.
패키지명을 쫓아가보니 내가 모르는 jar에 속했다.
다시 말해 어떤 jar을 하나 더 의존하는 것처럼 보였다. 그 어떤 jar를 INI_4.1.2.jar 라고 하자.
아래 테스트를 통해 더 확실히 알 수 있었다.
기존 앱에서 2.1.7.jar 파일은 그대로 두고, INI_4.1.2.jar 를 삭제했다.
앱에 아무런 빨간줄도 나오지 않았지만, 실행해보면 앱은 오류가 발생됐다.
앱은 2.1.7.jar 만 의존하고 있지만, 2.1.7.jar 가 INI_4.1.2.jar 를 의존하고 있는 것이다(라고 추정했다).
그래서 프로젝트를 다시 전부 롤백하고 다시 시작했다.
(1) 안드로이드 스튜디오 4.0 으로 프로젝트를 열고, 빌드해서 실행했다.
(2) 기존 libs 폴더에서 2.1.7.jar 와 INI_4.1.2.jar 를 삭제했다.
(3) libs 폴더에 library_name_v4.0.4.aar 파일을 추가하고 build.gradle 파일을 알맞게 수정했다.
(4) 관련 코드를 수정했다.
이유는 모르겠지만 4.0.0 aar 모듈을 사용했을 때는 com.업체명~ 패키지를 전부 net.업체명~ 패키지명으로 바꿔야 했고 메서드도 많이 사라져있어서 난감했는데,
4.0.4.aar 을 libs에 추가해서 사용해보니 com.업체명~ 패키지가 전부 그대로였고 메서드도 거의 일치하는 모습을 보였다.
이게 모듈 사용 여부의 차이인지 버전의 차이(4.0.0, 4.0.4)인지는 불분명하다.
심증으로는 모듈을 사용한다고 패키지명이 바뀔리가 없다고 생각하는데
버전의 차이는 더 말이 안된다.
2.1.7 은 com 패키지를 쓰고, 4.0.0 은 net 패키지를 쓰고, 4.0.4 는 com 패키지를 쓴다는 말이기 때문이다.
아무튼 작업을 끝내고 실행해보니 이번에도 2차 시도 때처럼 앱 위변조검증에 통과하는 문제가 있었다.
또 롤백을 해야하나 고민하다가 API 문서를 읽어봤다.
4.0.0 과 4.0.4 API문서가 조금 달랐다.
4.0.0 은 verify 메서드를 쓰라고 했고, 4.0.4는 SimpleVerify 메서드를 쓰라고 했다.
2.1.7을 쓰던 기존 앱은 verify 메서드를 쓰고 있었다.
이걸 SimpleVerify 메서드로 고치니까 드디어 앱위변조 검증 결과 실패가 떴다.
(=> 나중에 알게된 사실인데 verify 를 써야한다. 그리고 앱위변조 검증은 서버에 따로 앱을 업로드해서 해시값을 만드는게 아니라, 첫번째로 앱위변조 요청(verify 메서드)을 했을 경우 해시값을 서버에 저장하고 그 값을 기준으로 검증하는 것이었다.)
이제 평일이 되면 서버에 앱 해시값을 등록해서 통과를 시킬 차례다…
이게 되어야 진짜 성공이고 아니면 또 롤백행일지도…












