Skip to content

Nerojust/JetImagePicker

Repository files navigation

📸 JetImagePicker

A modern, Jetpack Compose-ready image picker library for Android.


Features

  1. Works seamlessly with Jetpack Compose, XML + Kotlin, or both.
  2. Supports Camera and Gallery.
  3. Clean handling of runtime permissions – even on Android 13+
  4. Supports multiple image selection and compression
  5. Provides structured result callbacks for success and error handling
  6. Just works – no hidden setup, no ActivityResultContracts, and no more permission nightmares!

🛠️ Setup

  1. Add to your project:

If using as a module:

implementation(project(":JetImagePicker"))

OR

implementation("com.github.nerojust:JetImagePicker:v1")

  1. Add to your settings.gradle:
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        maven { url = uri("https://jitpack.io") }
    }
}

🧱 Usage

1. Configure your AndroidManifest.xml

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <!-- for Android 13+ -->

<application>
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>
</application>

2. Create file_paths.xml in res/xml/

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <cache-path name="images" path="." />
</paths>

jetimagepicker

🧩 Example

✅ Image Picker Screen

@Composable
fun ImagePickerScreen() {
    val context = LocalContext.current
    var message by remember { mutableStateOf<String?>(null) }

    val pickerState = rememberJetImagePickerState(
        context = context,
        config = JetImagePickerConfig(
            enableCompression = true,
            compressionQuality = 70,
            allowMultiple = true,
            targetWidth = 1024,
            targetHeight = 1024
        )
    ) { result ->
        when (result) {
            is ImagePickerResult.Success -> message = null
            is ImagePickerResult.PermissionDenied -> {
                message = "Permission denied: ${result.permission}"
                //go ahead, all good
            }
            is ImagePickerResult.PermissionPermanentlyDenied -> {
                message = "Permanently denied: ${result.permission}"
                //do something
            }
            is ImagePickerResult.ShowRationale -> {
                message = "Please allow ${result.permission} to proceed."
                //do some business logic here
            }
        }
    }

    Column(Modifier.padding(16.dp)) {
        Button(onClick = pickerState.pickFromGallery) {
            Text("Pick from Gallery")
        }

        Spacer(Modifier.height(8.dp))

        Button(onClick = pickerState.captureWithCamera) {
            Text("Capture with Camera")
        }

        Spacer(Modifier.height(16.dp))

        when (pickerState.selectedImageUris.size) {
            1 -> ImagePreview(uri = pickerState.selectedImageUris.first())
            in 2..Int.MAX_VALUE -> MultiImagePreview(imageUris = pickerState.selectedImageUris)
        }

        message?.let {
            Text(
                text = it,
                color = MaterialTheme.colorScheme.error,
                style = MaterialTheme.typography.bodySmall
            )
        }
    }
}

📦 Configuration Options

JetImagePickerConfig(
    enableCompression = true,
    compressionQuality = 70, // 0–100
    allowMultiple = true,
    targetWidth = 1024,
    targetHeight = 1024
)

📤 Result Handling

Use the ImagePickerResult sealed class:

sealed class ImagePickerResult {
    data class Success(val uris: List<Uri>) : ImagePickerResult()
    data class PermissionDenied(val permission: String) : ImagePickerResult()
    data class PermissionPermanentlyDenied(val permission: String) : ImagePickerResult()
    data class ShowRationale(val permission: String) : ImagePickerResult()
}

❤️ Contributions

Contributions are welcome! Open issues, submit PRs, or suggest ideas.


🧑‍💻 Author

Made with 💙 by Nerojust


📄 License

MIT License. See LICENSE for details.

About

This is project containing the library JetImagePicker.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  

Languages