이 글에서는 프로젝트에 so 라이브러리를 추가하는 방법과, Apk에 라이브러리가 포함되었는지 확인하는 방법을 알아보겠습니다. so 라이브러리는 확장자가 so인 native library를 말합니다. 보통 JNI와 c++ 코드가 컴파일되어있습니다. 일반적으로 so 라이브러리를 사용하지 않기 때문에 개별적으로 폴더를 만들어서 파일을 포함시켜야 합니다.
먼저 프로젝트에 so 라이브러리를 추가하는 방법을 알아보고, 그 다음에 Apk에 so 라이브러리가 잘 포함되었는지 확인하는 방법을 알아보겠습니다.
프로젝트에 so 라이브러리 추가
안드로이드 스튜디오 프로젝트에 so 라이브러리를 포함시키려면 먼저 폴더를 생성해야 합니다.
src/main/ 아래에 jniLibs라는 폴더를 생성합니다. 그럼 전체적인 폴더 구조는 이렇게 됩니다.
app
 ├── libs
 └── src
     └── main
         ├── AndroidManifest.xml
         ├── java
         ├── res
         └── jniLibs   <--그리고 jniLibs에 so 라이브러리를 넣어주면 됩니다.
하지만 so 라이브러리는 CPU와 32/64bit 아키텍쳐에 의존적이기 때문에, 플랫폼 별로 다른 폴더에 넣어줘야 합니다.
아래 테이블은 플랫폼과 32/64bit에 따라 폴더 이름이 어떻게 설정되어야 하는지를 말해줍니다.
| 플랫폼 | 32비트 라이브러리 폴더 이름 | 64비트 라이브러리 폴더 이름 | 
|---|---|---|
| ARM | armeabi-v7a | arm64-v8a | 
| x86 | x86 | x86_64 | 
그래서 만약 ARM의 32/64bit를 모두 지원한다면 /jniLibs에 두개의 폴더를 생성하고 그 안에 so 라이브러리를 넣어야 합니다.
그럼 전체적인 폴더 구조는 아래처럼 보입니다.
app
 ├── libs
 └── src
     └── main
         ├── AndroidManifest.xml
         ├── java
         ├── res
         └── jniLibs
             ├── armeabi-v7a      <-- ARM 32bit
             │    └── *.so 파일들
             └── arm64-v8a        <-- ARM 64bit
                  └── *.so 파일들위처럼 폴더를 만들고 파일을 넣었다면 이제 빌드해보세요. 컴파일일된 Apk를 확인해보면 so 라이브러리가 포함된 것을 확인할 수 있습니다.
Apk에 so 라이브러리(native library)가 포함되었는지 확인
빌드를 하여 Apk가 생성되면 so 라이브러리가 포함되었는지 확인할 수 있습니다.
Apk파일은 zip이기 때문에 확장자를 zip으로 변경하여 압축을 풀면 /lib 폴더에 내가 넣은 so파일들이 있는 것을 확인할 수 있습니다.
하지만 안드로이드 스튜디오는 Analyze APK라는 기능을 제공합니다. 이것은 Apk에 포함된 파일을 분석하는 툴 입니다.
이 툴을 사용하면 Apk 안의 /lib 폴더에 so 라이브러리가 있는지 확인할 수 있습니다.
메뉴에서 [Build] -> [Analyze APK]를 눌러 툴을 실행합니다. 그리고 분석할 Apk를 찾아서 OK버튼을 누릅니다.
그럼 오른쪽 창에 Apk의 내부 파일들이 보입니다. /lib 폴더에 자신이 추가한 so가 있는지 확인하면 됩니다.
아래 그림은 Analyze APK로 apk를 분석한 결과입니다. 위에서 추가한 라이브러리가 모두 포함된 것을 볼 수 있습니다.
      
    
   
  
    
정리
안드로이드 프로젝트에 so 라이브러리를 포함하는 방법을 알아보았습니다.
자바 라이브러리는 기본적으로 폴더가 생성되어있지만 네이티브인 so 라이브러리를 사용하려면 개별적으로 폴더를 만들어줘야 합니다.
so 파일을 프로젝트에 포함시켰다면 산출물인 apk에 so가 포함되었는지 Analyze APK로 확인할 수 있습니다.
Related Posts
- Android 14 - 사진/동영상 파일, 일부 접근 권한 소개
- Android - adb push, pull로 파일 복사, 다운로드
- Android 14 - 암시적 인텐트 변경사항 및 문제 해결
- Jetpack Compose - Row와 Column
- Android 13, AOSP 오픈소스 다운로드 및 빌드
- Android 13 - 세분화된 미디어 파일 권한
- Android 13에서 Notification 권한 요청, 알림 띄우기
- Android 13에서 'Access blocked: ComponentInfo' 에러 해결
- 에러 해결: android gradle plugin requires java 11 to run. you are currently using java 1.8.
- 안드로이드 - 코루틴과 Retrofit으로 비동기 통신 예제
- 안드로이드 - 코루틴으로 URL 이미지 불러오기
- Android - 진동, Vibrator, VibrationEffect 예제
- Some problems were found with the configuration of task 에러 수정
- Query method parameters should either be a type that can be converted into a database column or a List
- 우분투에서 Android 12 오픈소스 다운로드 및 빌드
- Android - ViewModel을 생성하는 방법
- Android - Transformations.map(), switchMap() 차이점
- Android - Transformations.distinctUntilChanged() 소개
- Android - TabLayout 구현 방법 (+ ViewPager2)
- Android - 휴대폰 전화번호 가져오는 방법
- Android 12 - Splash Screens 알아보기
- Android 12 - Incremental Install (Play as you Download) 소개
- Android - adb 명령어로 bugreport 로그 파일 추출
- Android - adb 명령어로 App 데이터 삭제
- Android - adb 명령어로 앱 비활성화, 활성화
- Android - adb 명령어로 특정 패키지의 PID 찾기
- Android - adb 명령어로 퍼미션 Grant 또는 Revoke
- Android - adb 명령어로 apk 설치, 삭제
- Android - adb 명령어로 특정 패키지의 프로세스 종료
- Android - adb 명령어로 screen capture 저장
- Android - adb 명령어로 System 앱 삭제, 설치
- Android - adb 명령어로 settings value 확인, 변경
- Android 12 - IntentFilter의 exported 명시적 선언
- Android - adb 명령어로 공장초기화(Factory reset)
- Android - adb logcat 명령어로 로그 출력