Add the following dependency to your module build.gradle.kts
file:
implementation("com.mohamedrejeb.calf:calf-file-picker:0.5.1")
Calf File Picker allows you to pick files from the device storage.
Android | iOS |
---|---|
![]() |
![]() |
Desktop | Web |
---|---|
![]() |
![]() |
val scope = rememberCoroutineScope()
val context = LocalPlatformContext.current
val pickerLauncher = rememberFilePickerLauncher(
type = FilePickerFileType.Image,
selectionMode = FilePickerSelectionMode.Single,
onResult = { files ->
scope.launch {
files.firstOrNull()?.let { file ->
// Do something with the selected file
// You can get the ByteArray of the file
file.readByteArray(context)
}
}
}
)
Button(
onClick = {
pickerLauncher.launch()
},
modifier = Modifier.padding(16.dp)
) {
Text("Open File Picker")
}
FilePickerFileType
allows you to specify the type of files you want to pick:
FilePickerFileType.Image
- Allows you to pick images onlyFilePickerFileType.Video
- Allows you to pick videos onlyFilePickerFileType.ImageView
- Allows you to pick images and videos onlyFilePickerFileType.Audio
- Allows you to pick audio files onlyFilePickerFileType.Document
- Allows you to pick documents onlyFilePickerFileType.Text
- Allows you to pick text files onlyFilePickerFileType.Pdf
- Allows you to pick PDF files onlyFilePickerFileType.All
- Allows you to pick all types of filesFilePickerFileType.Folder
- Allows you to pick folders
You can filter files by custom mime types using FilePickerFileType.Custom
.
val type = FilePickerFileType.Custom(
listOf("text/plain")
)
You can also filter files by custom extensions using FilePickerFileType.Extension
.
val type = FilePickerFileType.Extension(
listOf("txt")
)
FilePickerSelectionMode
allows you to specify the selection mode of the file picker:
FilePickerSelectionMode.Single
- Allows you to pick a single fileFilePickerSelectionMode.Multiple
- Allows you to pick multiple files
- Read the
ByteArray
of the file using thereadByteArray
extension function:
val context = LocalPlatformContext.current
LaunchedEffect(file) {
val byteArray = file.readByteArray(context)
}
The
readByteArray
extension function is a suspending function, so you need to call it from a coroutine scope.
It's not recommended to use
readByteArray
extension function on large files, as it reads the entire file into memory. For large files, it's recommended to use the platform-specific APIs to read the file. You can read more about accessing the platform-specific APIs below.
- Check if the file exists using the
exists
extension function:
val context = LocalPlatformContext.current
val exists = file.exists(context)
- Get the file name using the
getName
extension function:
val context = LocalPlatformContext.current
val name = file.getName(context)
- Get the file path using the
getPath
extension function:
val context = LocalPlatformContext.current
val path = file.getPath(context)
- Check if the file is a directory using the
isDirectory
extension function:
val context = LocalPlatformContext.current
val isDirectory = file.isDirectory(context)
KmpFile is a wrapper around platform-specific APIs, you can access the native APIs for each platform using the following properties:
val uri: Uri = kmpFile.uri
val nsUrl: NSURL = kmpFile.url
val file: java.io.File = kmpFile.file
val file: org.w3c.files.File = kmpFile.file