Project/사이드 프로젝트

[React Native 개발] Android 최근 항목(Recent)에서 이미지 여러장 가져오기

아밍나 2025. 6. 14. 12:45
728x90

React Native로 앱 개발 중 갤러리에서 이미지를 가져오는 기능이 필요했다.

보통 expo-image-picker나 react-native-image-picker를 사용하지만,

  1. 나는 expo를 사용하지 않는다

  2. react-native-image-picker는 SDK 33이하에서 사용 가능하다. (나는 SDK 34 사용)

따라서 두 라이브러리를 사용하지 않고 이미지를 가져오려면 코틀린 코드를 작성해야만 했다.

 

Kotlin은 사용해본 적 없었지만 이번 기회에 사용해보았다... (TMI를 말하자면, 다른 라이브러리 있나 찾을 시간에 진작에 코틀린으로 구현했으면 시간이 훨씬 단축됐을 거다...😢)

 

참고로 현재 게시물은 갤러리가 아닌 최근 항목에서 이미지를 가지고 오는 코드 관련 내용들을 서술한다.


0. AndroidManifest.xml에 권한 추가

파일 위치: 프로젝트 > android > app > src > main > AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 하단에 작성 -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

1. Native Module 구현

MultiImagePickerModule.kt

파일 위치: 프로젝트 > android > app > src > main > java\com\패키지이름 > 폴더명 > MultiImagePickerModule.kt

package com.프로젝트이름.폴더명

import android.app.Activity
import android.content.Intent
import com.facebook.react.bridge.*

class MultiImagePickerModule(private val reactContext: ReactApplicationContext) :
    ReactContextBaseJavaModule(reactContext), ActivityEventListener {

    private var promise: Promise? = null
    private val REQUEST_CODE = 23456

    init {
        reactContext.addActivityEventListener(this)
    }

    override fun getName() = "MultiImagePickerModule"

    @ReactMethod
    fun pickImages(promise: Promise) {
        this.promise = promise
        val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
            addCategory(Intent.CATEGORY_OPENABLE)
            type = "image/*"
            putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
        }

        currentActivity?.startActivityForResult(intent, REQUEST_CODE)
            ?: promise.reject("NO_ACTIVITY", "Activity is null")
    }

    override fun onActivityResult(activity: Activity?, requestCode: Int, resultCode: Int, data: Intent?) {
        if (requestCode != REQUEST_CODE || promise == null) return

        if (resultCode == Activity.RESULT_OK) {
            val uriList = mutableListOf<String>()
            data?.let {
                if (it.clipData != null) {
                    for (i in 0 until it.clipData!!.itemCount) {
                        val uri = it.clipData!!.getItemAt(i).uri
                        uriList.add(uri.toString())
                    }
                } else if (it.data != null) {
                    uriList.add(it.data!!.toString())
                }
            }
            promise?.resolve(Arguments.fromList(uriList))
        } else {
            promise?.reject("CANCELLED", "User cancelled")
        }
        promise = null
    }

    override fun onNewIntent(intent: Intent?) {}
}

2. Package 등록

MultiImagePickerPackage.kt

파일 위치: 프로젝트 > android > app > src > main > java\com\패키지이름 > 폴더명 > MultiImagePickerPackage .kt

package com.프로젝트이름.폴더명

import com.facebook.react.ReactPackage
import com.facebook.react.bridge.*
import com.facebook.react.uimanager.ViewManager

class MultiImagePickerPackage : ReactPackage {
    override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
        return listOf(MultiImagePickerModule(reactContext))
    }

    override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> = emptyList()
}

3. MainApplication.kt 연결

파일 위치: 프로젝트 > android > app > src > main > java\com\패키지이름 > 폴더명 > MainApplication.kt

//프로젝트 상단에 import도 해야함
import com.프로젝트명.폴더명.MultiImagePickerPackage

class MainApplication : Application(), ReactApplication {

  override val reactNativeHost: ReactNativeHost =
      object : DefaultReactNativeHost(this) {
        override fun getPackages(): List<ReactPackage> =
            PackageList(this).packages.apply {
              // 여기에 추가
              add(MultiImagePickerPackage())
            }
        ...

4. JS에서 호출

// Native Module 호출 함수
import { NativeModules } from 'react-native';

export const pickImages = async (): Promise<string[]> => {
  const { MultiImagePickerModule } = NativeModules;
  
  if (!MultiImagePickerModule) 
  	throw new Error('Native module not linked');
  
  return await MultiImagePickerModule.pickImages();
};

// 사용 예
const onSelectImages = async () => {
  try {
    const uris = await pickImages(); //[] 반환
    console.log('선택된 이미지 URI:', uris);
  } catch (e) {
    console.error('이미지 선택 실패:', e);
  }
};

Native 코드를 수정했으므로 gradle 빌드를 다시 수행해야한다. 아래 글을 참고하면 된다.

https://it-amin.tistory.com/136

 

[React Native (RN)] Android Native 코드 수정 후 절차

React Native 구성React Native 앱은 두 부분으로 나뉜다.1. JavaScript 코드 Metro bundler로 런타임에 로딩Metro 서버를 통해 즉시 반영2. Native 코드 (Java/Kotlin, C++)Gradle로 컴파일 (.apk로 포함)JS코드처럼 바로 반

it-amin.tistory.com


 

위 코드를 작성 후 실행을 하면 최근 항목에서 사진들을 가지고 올 수 있다.

728x90
반응형