Accessing the device gallery is a common feature in many Android applications, especially those related to photo sharing, editing, or social media. However, developers often encounter an issue where a Kotlin-based Android app cannot access the gallery due to permission misconfigurations or outdated APIs. This article explains how to solve the “Kotlin app can’t access gallery” problem with a complete example and covers all related best practices.

Common Causes Why Kotlin App Can’t Access Gallery
There are several possible reasons:
- Runtime permissions not requested properly
- Missing
READ_EXTERNAL_STORAGE
permission in the manifest - Using incorrect intent to open gallery
- Scoped Storage restrictions (Android 10 and above)
- Incorrect handling of activity result
Step-by-Step Guide to Fix the Issue
1. Add Required Permissions in AndroidManifest.xml
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
Note: On Android 13+, use
READ_MEDIA_IMAGES
. On Android 10+,READ_EXTERNAL_STORAGE
must be granted at runtime.
2. Check Android Version and Request Permissions at Runtime
Use Kotlin’s ActivityCompat
to handle permission request:
private val galleryPermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted -> if (isGranted) { openGallery() } else { Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show() } } private fun checkGalleryPermission() { val permission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { Manifest.permission.READ_MEDIA_IMAGES } else { Manifest.permission.READ_EXTERNAL_STORAGE } if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) { galleryPermissionLauncher.launch(permission) } else { openGallery() } }
3. Launch Gallery with Intent
Make sure you use the correct Intent to access the gallery:
private val galleryLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == Activity.RESULT_OK && result.data != null) { val selectedImageUri = result.data!!.data // Use the selected image URI as needed imageView.setImageURI(selectedImageUri) } } private fun openGallery() { val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) intent.type = "image/*" galleryLauncher.launch(intent) }
4. Call Permission Check from Button
binding.btnPickImage.setOnClickListener { checkGalleryPermission() }
5. Example Layout XML
Here’s a minimal layout for testing:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" android:padding="16dp"> <ImageView android:id="@+id/imageView" android:layout_width="250dp" android:layout_height="250dp" android:scaleType="centerCrop" android:background="@android:color/darker_gray" /> <Button android:id="@+id/btnPickImage" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Pick Image from Gallery" android:layout_marginTop="16dp" /> </LinearLayout>
6. Don’t Forget About Scoped Storage
From Android 10 (API 29) and above, apps can’t access arbitrary file paths directly. Always rely on Uri
and ContentResolver
when dealing with gallery files. Here’s how to get the real path from a URI if needed:
private fun getRealPathFromURI(uri: Uri): String? { val projection = arrayOf(MediaStore.Images.Media.DATA) val cursor = contentResolver.query(uri, projection, null, null, null) return cursor?.use { val columnIndex = it.getColumnIndexOrThrow(MediaStore.Images.Media.DATA) it.moveToFirst() it.getString(columnIndex) } }
Final Words
To ensure your Kotlin app can access the device’s image gallery:
- Properly define permissions in the manifest
- Always check and request permissions at runtime
- Use the correct intent (
Intent.ACTION_PICK
) to access media - Handle results using the modern
ActivityResultContracts
With this approach, you’ll eliminate common errors like “Permission denied”, “App crashes when selecting image”, or “Image URI null”.
For official reference, you can also check the Android developer documentation regarding media access in scoped storage.