Android应用中使用Kotlin实现点击按钮打开文件选择器上传图片
Alright, let's walk through exactly how to implement this feature—clicking a button to open a file picker and select an image—in your Android app with Kotlin. We'll use the modern Activity Result API (since the old onActivityResult is deprecated) and the Storage Access Framework (SAF), which is recommended for Android 10+ to handle file access properly.
Step 1: Add a Button to Your Layout
First, add a button to your XML layout (e.g., res/layout/activity_main.xml) that users will tap to trigger the file picker:
<Button android:id="@+id/btnSelectImage" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Select Image" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toBottomOf="parent"/>
Step 2: Set Up the Activity Result Launcher
In your Kotlin Activity (e.g., MainActivity.kt), register an ActivityResultLauncher to handle the result when the user selects an image. This replaces the outdated onActivityResult method:
import android.content.Intent import android.net.Uri import android.os.Bundle import android.widget.Button import androidx.appcompat.app.AppCompatActivity import androidx.activity.result.contract.ActivityResultContracts class MainActivity : AppCompatActivity() { // Register launcher to handle file picker results private val pickImageLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == RESULT_OK) { // Get the selected image's Uri val selectedImageUri: Uri? = result.data?.data selectedImageUri?.let { // Do something with the Uri—like display it, upload it, etc. // Example: imageView.setImageURI(it) println("Selected image URI: $it") } } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Attach click listener to the button val selectImageBtn = findViewById<Button>(R.id.btnSelectImage) selectImageBtn.setOnClickListener { openImagePicker() } } // Function to launch the image file picker private fun openImagePicker() { val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply { // Filter results to only image files type = "image/*" // Allow multiple selection? Set to true if needed putExtra(Intent.EXTRA_ALLOW_MULTIPLE, false) // Ensure the Uri can be accessed across app restarts addCategory(Intent.CATEGORY_OPENABLE) } pickImageLauncher.launch(intent) } }
Key Notes for Smooth Implementation
- Scoped Storage Compatibility: Using
ACTION_OPEN_DOCUMENTworks seamlessly with Android 10+ scoped storage, so you don't need to requestREAD_EXTERNAL_STORAGEpermission for Android 13+. For older versions (API < 29), you'll need to handle runtime permissions (see below). - Persisting Access: If you need to access the selected image after the app restarts, use
contentResolver.takePersistableUriPermission()to retain access to the Uri. - Multiple Images: To let users select multiple images, set
EXTRA_ALLOW_MULTIPLEtotrueand loop throughresult.data?.clipDatato get all selected Uris.
Handling Runtime Permissions (For API < 29)
If your app targets Android 9 or lower, add this permission to AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Then, add permission checking before launching the picker:
import android.content.pm.PackageManager import android.os.Build import androidx.core.content.ContextCompat // Add a permission request launcher private val requestPermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted -> if (isGranted) { openImagePicker() } else { // Show a message to the user explaining why permission is needed println("Storage permission denied—can't access images") } } // Update the button click listener selectImageBtn.setOnClickListener { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { requestPermissionLauncher.launch(android.Manifest.permission.READ_EXTERNAL_STORAGE) } else { openImagePicker() } } else { openImagePicker() } }
That's all you need! This setup lets users tap the button, open the system file picker, select an image, and gives you the Uri to use for uploads or display.
内容的提问来源于stack exchange,提问作者Amita

