Filepicker
Android file and image picker library without permissions.
Install / Use
/learn @Atwa/FilepickerREADME
FilePicker
Android library to facilitate files and image picking up process whether from storage or camera and ability to convert them to request bodies without permission.
The goal of this library is to get rid of the hassle of file picking up handling and reduce effort made in uploading them to server without the need to ask use for a single permission.
Features:
- Launch different file types picking requests (Image ,Video ,Pdf and File for general).
- Get a callback with related meta according to the request type.
- Meta can be (fileName,size in Kb, bitmap and file object).
- Convert picked up files to request bodies to use them with api requests to upload them to server.
- Not a single permission is required.
- Support Jetpack Compose.
- Progressive file picking updates for large files.
Dependency :
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.atwa:filepicker:3.2.0'
}
Usage :
-
Initialize instance in activity/fragment as member variable.
private val filePicker = FilePicker.getInstance(this) -
File picking with progress
fun pickFile() { filePicker.pickFile( onProgress = { progress -> tvMsg.text = "Picking file... ${"%.2f".format(progress * 100)}%" }, onFilePicked = { fileResult -> val name: String? = meta?.name val sizeKb: Int? = meta?.sizeKb val file: File? = meta?.file } ) } -
Multiple Files picking with progress
fun pickFile() { filePicker.pickMultiFiles( onProgress = { fileIndex, totalFilesNum, fileProgress -> tvMsg.text = "Picking file ${fileIndex + 1} of $totalFilesNum ... ${"%.2f".format(fileProgress * 100)}%" }, onFilesPicked = { filesResult -> tvMsg.text = "${filesResult.size} Files picked .." ?: "No File Selected" } ) } -
Image picking
fun pickImage() { filePicker.pickImage() { result -> val name : String? = result?.name val sizeKb : Int? = result?.sizeKb val file : File? = result?.file val bitmap : Bitmap? = result?.bitmap } } -
Image multi picking
fun pickMultiImage() { filePicker.pickMultiImage { list -> list.forEach { result -> val name : String? = result?.name val sizeKb : Int? = result?.sizeKb val file : File? = result?.file val bitmap : Bitmap? = result?.bitmap } } } -
Image capture
fun captureImage() { filePicker.captureCameraImage() { result -> val name : String? = result?.name val sizeKb : Int? = result?.sizeKb val file : File? = result?.file val bitmap : Bitmap? = result?.bitmap } } -
Video capture
fun captureVideo() { filePicker.captureCameraVideo() { result -> val name: String? = result?.name val sizeKb: Int? = result?.sizeKb val file: File? = result?.file val thumbnail: Bitmap? = result?.thumbnail } } -
Pdf picking
fun pickPdf() { filePicker.pickPdf() { result -> val name: String? = result?.name val sizeKb: Int? = result?.sizeKb val file: File? = result?.file } } -
Video picking
fun pickVideo() { filePicker.pickVideo() { result -> val name: String? = result?.name val sizeKb: Int? = result?.sizeKb val file: File? = result?.file val thumbnail: Bitmap? = result?.thumbnail } } -
File picking
fun pickFile() { filePicker.pickFile() { result -> val name: String? = result?.name val sizeKb: Int? = result?.sizeKb val file: File? = result?.file } } -
File picking filtered with MIME type
fun pickMimeFile() { filePicker.pickMimeFile(mimeType = "application/pdf") { result -> val name: String? = result?.name val sizeKb: Int? = result?.sizeKb val file: File? = result?.file } } -
File picking from Initial directory
fun pickPathFile() { filePicker.pickPathFile(initialDirectoryPath = "") { result -> val name: String? = result?.name val sizeKb: Int? = result?.sizeKb val file: File? = result?.file } } -
File picking from Initial directory with MIME type
fun pickFile() { filePicker.pickFile(initialDirectoryPath = "",mimeType = "application/pdf") { result -> val name: String? = result?.name val sizeKb: Int? = result?.sizeKb val file: File? = result?.file } } -
File multi picking
fun pickMultiFiles() { filePicker.pickMultiFiles { list -> list.forEach { result -> val name: String? = result?.name val sizeKb: Int? = result?.sizeKb val file: File? = result?.file } } } -
File multi picking filtered with MIME type
fun pickMultiFiles() { filePicker.pickMultiMimeFiles(mimeType = "application/pdf") { list -> list.forEach { result -> val name: String? = result?.name val sizeKb: Int? = result?.sizeKb val file: File? = result?.file } } } -
File multi picking with initial directory path
fun pickMultiFiles() { filePicker.pickMultiPathFiles(initialDirectoryPath = "") { list -> list.forEach { result -> val name: String? = result?.name val sizeKb: Int? = result?.sizeKb val file: File? = result?.file } } } -
File picking from Initial directory with MIME type
fun pickMultiFiles() { filePicker.pickMultiFiles(initialDirectoryPath = "",mimeType = "application/pdf") { list -> list.forEach { result -> val name: String? = result?.name val sizeKb: Int? = result?.sizeKb val file: File? = result?.file } } } -
File converting to request body
fun convertFile() { val file: File = File("file") val requestBody: RequestBody = FileConverter.getInstance() .toRequestBody(file, FileConverter.getInstance().fileMediaType) }
Compose Usage :
@Composable
fun FilePickerDemo(modifier: Modifier = Modifier) {
var message by remember { mutableStateOf("Hello World!") }
val filePicker = ComposeFilePicker.getInstance(LocalContext.current)
val pickerLauncher = filePicker.fileLauncher(
onProgress = { progress ->
message = "Picking file... ${"%.2f".format(progress * 100)}%"
},
onFilePicked = { fileResult ->
message = fileResult?.let { "File picked: $it" } ?: "No file picked"
}
)
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = message,
modifier = modifier
)
Button({ pickerLauncher.launch() }) {
Text("Pick file")
}
}
}
Demo :
Version history
| Version | Release note | |---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1.0.0 | Initial release. | | 1.0.1 | Increase buffer size (8GB) to be larger for better performance. | | 1.0.3 | Fix bug : LifecycleOwner Activity is attempting to register while current state is RESUMED. | | 1.0.4 | Enhancement : Avoid possible activity reference leaking. <br /> Feature : Implement camera image picker. | | 1.0.5 | Feature : Support fragments. <br /> Feature : Implement file picking from initial directory. <br /> fix : o
Related Skills
docs-writer
99.6k`docs-writer` skill instructions As an expert technical writer and editor for the Gemini CLI project, you produce accurate, clear, and consistent documentation. When asked to write, edit, or revie
model-usage
341.8kUse CodexBar CLI local cost usage to summarize per-model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.
ddd
Guía de Principios DDD para el Proyecto > 📚 Documento Complementario : Este documento define los principios y reglas de DDD. Para ver templates de código, ejemplos detallados y guías paso
arscontexta
2.9kClaude Code plugin that generates individualized knowledge systems from conversation. You describe how you think and work, have a conversation and get a complete second brain as markdown files you own.
