This library is built to provide other developers with an easy way to implement an image picker in
Android applications using the latest Android technologies. It supports Activities, Fragments with
XML, and Jetpack Compose.
Support me, and I would appreciate any feedback you provide.
Note: The example project does not include examples for all methods.
The library contains/features:
- Picker for a single image from the gallery.
- Picker for multiple images from the gallery (up to 9 images).
- Camera picker for a single image (with permission handling - manage the scenario where camera permission is permanently denied by directing the user to the app settings to modify the permission or can use the onPermanentCameraPermissionDenied() callback to implement your own custom logic).
- Video picker.
- Retrieve the base64 value.
- Image scaling (resize) β available only for images.
- All of the above features are also supported in Jetpack Compose.
- New updates coming soon! Feel free to share your suggestions.
Reasons to use this library
- It supports both Activity and Fragment with XML, as well as Jetpack Compose, ensuring compatibility with various Android development approaches.
- The library provides a user-friendly way to integrate image picking functionalities, saving time and effort.
- It offers advanced features like base64 encoding support and image scaling, enhancing your app's image handling capabilities.
Gradle Version 8.9.2
Kotlin Version 2.1.20
JDK Version 17
Minimum SDK 24
Target SDK 35
Build Tool Version 35.0.1
THE BETA RELEASES MAY CONTAIN MAJOR OR MINOR CHANGES.
Important
Breaking changes from the version 2.3.0 and higher
takeSingleCameraImage()
changed to takeSingleCameraImage(context = context)
takeSingleCameraImageWithBase64Value()
changed to
takeSingleCameraImageWithBase64Value(context = context)
Important
Check my article with the implementation :
point_right: ImagePickerAndroid - My Android Image Picker Library π§βπ» - Medium :
point_left:
implementation 'com.github.NicosNicolaou16:ImagePickerAndroid:2.3.2'
allprojects {
repositories {
maven { url "https://jitpack.io" }
}
}
implementation("com.github.NicosNicolaou16:ImagePickerAndroid:2.3.2")
dependencyResolutionManagement {
//...
repositories {
//...
maven { url = uri("https://jitpack.io") }
}
}
[versions]
# other versions here...
imagePickerAndroid = "2.3.2"
[libraries]
# other libraries here...
image-picker-android = { group = "com.github.NicosNicolaou16", name = "ImagePickerAndroid", version.ref = "imagePickerAndroid" }
implementation(libs.image.picker.android)
dependencyResolutionManagement {
//...
repositories {
//...
maven { url = uri("https://jitpack.io") }
}
}
class MainActivity : AppCompatActivity(), ImagePickerInterface {
//...
private var imagePicker: ImagePicker? = null
//...
fun initImagePicker() {
//Builder
//Note: fragmentActivity or fragment are mandatory one of them
imagePicker = ImagePicker(
fragmentActivity = this, //activity instance - private
fragment = this, // fragment instance - private
coroutineScope = lifecycleScope, // mandatory - coroutine scope from activity or fragment - private
scaleBitmapModelForSingleImage = ScaleBitmapModel(
height = 100,
width = 100
), // optional, change the scale for image, by default is null
scaleBitmapModelForMultipleImages = ScaleBitmapModel(
height = 100,
width = 100
), // optional, change the scale for image, by default is null
scaleBitmapModelForCameraImage = ScaleBitmapModel(
height = 100,
width = 100
), // optional, change the scale for image, by default is null
enabledBase64ValueForSingleImage = true, // optional, by default is false - private
enabledBase64ValueForMultipleImages = true, // optional, by default is false - private
enabledBase64ValueForCameraImage = true, // optional, by default is false - private
imagePickerInterface = this, // call back interface
shouldRedirectedToSettingsIfPermissionDenied = false // optional, by default is true - private, if it set false, need to call the callback onPermanentCameraPermissionDenied()
)
//...other image picker initialization method(s)
}
//...
}
imagePicker?.initPickSingleImageFromGalleryResultLauncher()
imagePicker?.initPickMultipleImagesFromGalleryResultLauncher()
imagePicker?.initTakePhotoWithCameraResultLauncher()
imagePicker?.initPickSingleVideoFromGalleryResultLauncher()
imagePicker?.pickSingleImageFromGallery()
imagePicker?.pickMultipleImagesFromGallery()
imagePicker?.takeSinglePhotoWithCamera()
imagePicker?.pickSingleVideoFromGallery()
class MainActivity : AppCompatActivity(), ImagePickerInterface {
//...
override fun onGallerySingleImage(bitmap: Bitmap?, uri: Uri?) {
super.onGalleryImage(bitmap, uri)
//...your code here
}
override fun onCameraImage(bitmap: Bitmap?) {
super.onCameraImage(bitmap)
//...your code here
}
override fun onMultipleGalleryImages(
bitmapList: MutableList<Bitmap>?,
uriList: MutableList<Uri>?
) {
super.onMultipleGalleryImages(bitmapList, uriList)
//...your code here
}
override fun onGallerySingleImageWithBase64Value(
bitmap: Bitmap?,
uri: Uri?,
base64AsString: String?
) {
super.onGalleryImage(bitmap, uri, base64AsString)
//...your code here
}
override fun onCameraImageWithBase64Value(bitmap: Bitmap?, base64AsString: String?) {
super.onCameraImage(bitmap, base64AsString)
//...your code here
}
override fun onMultipleGalleryImagesWithBase64Value(
bitmapList: MutableList<Bitmap>?,
uriList: MutableList<Uri>?,
base64AsStringList: MutableList<String>?
) {
super.onMultipleGalleryImages(bitmapList, uriList, base64AsStringList)
//...your code here
}
override fun onGallerySingleVideo(uri: Uri?) {
super.onGallerySingleVideo(uri)
//...your code here
}
// Need to call and set the shouldRedirectedToSettingsIfPermissionDenied = false from builder to use this callback
override fun onPermanentCameraPermissionDenied() {
super.onPermanentCameraPermissionDenied()
}
}
PickSingleImage(
scaleBitmapModel = ScaleBitmapModel(
height = 100,
width = 100
), listener = { bitmap, uri ->
//...your code here
})
PickSingleImageWithBase64Value(
scaleBitmapModel = null,
listener = { bitmap, uri, base64 ->
//...your code here
})
PickMultipleImages(
scaleBitmapModel = null,
listener = { bitmapList, uriList ->
//...your code here
})
PickMultipleImagesWithBase64Values(
scaleBitmapModel = null,
listener = { bitmapList, uriList, base64List ->
//...your code here
})
TakeSingleCameraImage(
scaleBitmapModel = null,
listener = { bitmap, uri ->
//...your code here
})
TakeSingleCameraImageWithBase64Value(
scaleBitmapModel = null,
listener = { bitmap, uri, base64 ->
//...your code here
})
PickSingleVideo(listener = { uri ->
//...your code here
})
pickSingleImage()
pickSingleImageWithBase64Value()
pickMultipleImages()
pickMultipleImagesWithBase64Values()
/**
* onPermanentCameraPermissionDeniedCallBack is optional
* */
takeSingleCameraImage(context = context, onPermanentCameraPermissionDeniedCallBack {
// show custom dialog - showDialog.value = true
})
takeSingleCameraImageWithBase64Value(context = onPermanentCameraPermissionDeniedCallBack {
// show custom dialog - showDialog.value = true
})
pickSingleVideo()
@Composable
fun ImagePicker() {
val context = LocalContext.current
val bitmapValue = remember {
mutableStateOf(Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888))
}
//Initialize the call back
PickSingleImage(scaleBitmapModel = null, listener = { bitmap, uri ->
if (bitmap != null) {
bitmapValue.value = bitmap
}
})
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(20.dp, alignment = Alignment.Top),
horizontalAlignment = Alignment.CenterHorizontally,
) {
//other code
Button(modifier = Modifier.size(150.dp, 50.dp), onClick = {
//pick image from the gallery
pickSingleImage()
}) {
Text(
text = stringResource(R.string.pick_single_image),
style = TextStyle(textAlign = TextAlign.Center)
)
}
//other code
}
}