🎯 Ejemplos recomendados
Balanced sample collections from various categories for you to explore
Ejemplos de Características de Escritorio Android Kotlin
Ejemplos de características de escritorio Android Kotlin incluyendo cuadros de diálogo de archivos, cuadros de mensajes y bandeja del sistema
💻 Cuadros de Mensajes kotlin
🟢 simple
⭐⭐⭐
Mostrar diálogos de alerta, avisos de confirmación, mensajes toast y snackbar
⏱️ 20 min
🏷️ kotlin, android, ui, dialogs
Prerequisites:
Basic Kotlin, Android SDK
// Android Kotlin Message Box Examples
// Using AlertDialog, Toast, and Snackbar
import android.app.AlertDialog
import android.content.Context
import android.content.DialogInterface
import android.widget.EditText
import android.widget.Toast
import com.google.android.material.snackbar.Snackbar
import androidx.appcompat.app.AppCompatActivity
import android.view.LayoutInflater
import android.view.View
// 1. Alert Dialogs
class AlertDialogHelper(private val activity: AppCompatActivity) {
// Simple alert dialog
fun showAlert(title: String, message: String) {
AlertDialog.Builder(activity)
.setTitle(title)
.setMessage(message)
.setPositiveButton("OK") { dialog, which ->
println("OK clicked")
}
.show()
}
// Alert with callback
fun showAlertWithCallback(
title: String,
message: String,
onOkClicked: () -> Unit
) {
AlertDialog.Builder(activity)
.setTitle(title)
.setMessage(message)
.setPositiveButton("OK") { dialog, which ->
onOkClicked()
}
.show()
}
// Confirmation dialog
fun showConfirmDialog(
title: String,
message: String,
onConfirm: () -> Unit,
onCancel: () -> Unit = {}
) {
AlertDialog.Builder(activity)
.setTitle(title)
.setMessage(message)
.setPositiveButton("Yes") { dialog, which ->
onConfirm()
}
.setNegativeButton("No") { dialog, which ->
onCancel()
}
.show()
}
// Dialog with icon
fun showAlertWithIcon(
title: String,
message: String,
iconId: Int
) {
AlertDialog.Builder(activity)
.setTitle(title)
.setMessage(message)
.setIcon(iconId)
.setPositiveButton("OK", null)
.show()
}
// Dialog with neutral button
fun showThreeButtonDialog(
title: String,
message: String,
onPositive: () -> Unit = {},
onNegative: () -> Unit = {},
onNeutral: () -> Unit = {}
) {
AlertDialog.Builder(activity)
.setTitle(title)
.setMessage(message)
.setPositiveButton("Yes") { _, _ -> onPositive() }
.setNegativeButton("No") { _, _ -> onNegative() }
.setNeutralButton("Cancel") { _, _ -> onNeutral() }
.show()
}
}
// 2. Input Dialogs
class InputDialogHelper(private val activity: AppCompatActivity) {
// Single input dialog
fun showInputDialog(
title: String,
hint: String,
onConfirm: (String) -> Unit
) {
val input = EditText(activity)
input.hint = hint
AlertDialog.Builder(activity)
.setTitle(title)
.setView(input)
.setPositiveButton("OK") { dialog, which ->
val text = input.text.toString()
onConfirm(text)
}
.setNegativeButton("Cancel", null)
.show()
}
// Multi-input dialog
fun showMultiInputDialog(
title: String,
fields: List<InputField>,
onConfirm: (Map<String, String>) -> Unit
) {
val container = activity.layoutInflater
.inflate(android.R.layout.select_dialog_multiselect, null) as ViewGroup
val inputs = mutableMapOf<String, EditText>()
for (field in fields) {
val layout = activity.layoutInflater.inflate(
android.R.layout.simple_list_item_1,
container,
false
) as ViewGroup
val label = EditText(activity)
label.hint = field.hint
label.inputType = field.inputType
container.addView(label)
inputs[field.key] = label
}
AlertDialog.Builder(activity)
.setTitle(title)
.setView(container)
.setPositiveButton("OK") { _, _ ->
val values = inputs.mapValues { it.text.toString() }
onConfirm(values)
}
.setNegativeButton("Cancel", null)
.show()
}
// Password input dialog
fun showPasswordDialog(
title: String,
hint: String = "Enter password",
onConfirm: (String) -> Unit
) {
val input = EditText(activity)
input.hint = hint
input.inputType = android.text.InputType.TYPE_CLASS_TEXT or
android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD
AlertDialog.Builder(activity)
.setTitle(title)
.setView(input)
.setPositiveButton("OK") { _, _ ->
onConfirm(input.text.toString())
}
.setNegativeButton("Cancel", null)
.show()
}
// Data class for input field
data class InputField(
val key: String,
val hint: String,
val inputType: Int = android.text.InputType.TYPE_CLASS_TEXT
)
}
import android.view.ViewGroup
// 3. List Dialogs
class ListDialogHelper(private val activity: AppCompatActivity) {
// Single choice list
fun showSingleChoiceList(
title: String,
items: List<String>,
onSelected: (Int) -> Unit
) {
var selectedItem = 0
AlertDialog.Builder(activity)
.setTitle(title)
.setSingleChoiceItems(items.toTypedArray(), selectedItem) { dialog, which ->
selectedItem = which
}
.setPositiveButton("OK") { dialog, which ->
onSelected(selectedItem)
}
.setNegativeButton("Cancel", null)
.show()
}
// Multi-choice list
fun showMultiChoiceList(
title: String,
items: List<String>,
onSelected: (Set<Int>) -> Unit
) {
val selectedItems = mutableSetOf<Int>()
AlertDialog.Builder(activity)
.setTitle(title)
.setMultiChoiceItems(items.toTypedArray(), null) { dialog, which, isChecked ->
if (isChecked) {
selectedItems.add(which)
} else {
selectedItems.remove(which)
}
}
.setPositiveButton("OK") { dialog, which ->
onSelected(selectedItems)
}
.setNegativeButton("Cancel", null)
.show()
}
// Simple list dialog
fun showListDialog(
title: String,
items: List<String>,
onSelected: (String) -> Unit
) {
AlertDialog.Builder(activity)
.setTitle(title)
.setItems(items.toTypedArray()) { dialog, which ->
onSelected(items[which])
}
.show()
}
}
// 4. Toast Messages
class ToastHelper(private val context: Context) {
// Short toast
fun showShort(message: String) {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
}
// Long toast
fun showLong(message: String) {
Toast.makeText(context, message, Toast.LENGTH_LONG).show()
}
// Custom duration toast
fun showCustom(message: String, durationMs: Int) {
val toast = Toast.makeText(context, message, Toast.LENGTH_SHORT)
toast.duration = durationMs
toast.show()
}
// Toast with position
fun showWithPosition(
message: String,
gravity: Int,
xOffset: Int,
yOffset: Int
) {
val toast = Toast.makeText(context, message, Toast.LENGTH_SHORT)
toast.setGravity(gravity, xOffset, yOffset)
toast.show()
}
// Custom view toast
fun showCustomView(message: String) {
val inflater = LayoutInflater.from(context)
val layout = inflater.inflate(android.R.layout.simple_list_item_1, null)
// Assuming there's a TextView in the layout
// val textView = layout.findViewById<TextView>(android.R.id.text1)
// textView.text = message
val toast = Toast(context)
toast.view = layout
toast.duration = Toast.LENGTH_SHORT
toast.show()
}
}
// 5. Snackbar
class SnackbarHelper {
// Show simple snackbar
fun show(view: View, message: String) {
Snackbar.make(view, message, Snackbar.LENGTH_SHORT).show()
}
// Show long snackbar
fun showLong(view: View, message: String) {
Snackbar.make(view, message, Snackbar.LENGTH_LONG).show()
}
// Snackbar with action
fun showWithAction(
view: View,
message: String,
actionText: String,
onActionClicked: () -> Unit
) {
Snackbar.make(view, message, Snackbar.LENGTH_LONG)
.setAction(actionText) {
onActionClicked()
}
.show()
}
// Indefinite snackbar
fun showIndefinite(view: View, message: String) {
Snackbar.make(view, message, Snackbar.LENGTH_INDEFINITE)
.setAction("Dismiss") { }
.show()
}
// Custom snackbar with callback
fun showWithCallback(
view: View,
message: String,
onDismissed: () -> Unit
) {
val snackbar = Snackbar.make(view, message, Snackbar.LENGTH_SHORT)
snackbar.addCallback(object : Snackbar.Callback() {
override fun onDismissed(transientBottomBar: Snackbar, event: Int) {
onDismissed()
}
})
snackbar.show()
}
// Snackbar with custom styling
fun showStyled(view: View, message: String, backgroundColor: Int) {
val snackbar = Snackbar.make(view, message, Snackbar.LENGTH_SHORT)
snackbar.view.setBackgroundColor(backgroundColor)
snackbar.show()
}
}
// 6. Progress Dialogs
class ProgressDialogHelper(private val activity: AppCompatActivity) {
// Simple progress dialog
fun showProgressDialog(title: String, message: String): AlertDialog {
val builder = AlertDialog.Builder(activity)
val inflater = activity.layoutInflater
val dialogView = inflater.inflate(android.R.layout.select_dialog_item, null)
builder.setTitle(title)
.setMessage(message)
.setView(dialogView)
.setCancelable(false)
val dialog = builder.create()
dialog.show()
return dialog
}
// Indeterminate progress
fun showIndeterminateProgress(title: String, message: String): AlertDialog {
return showProgressDialog(title, message)
}
// Horizontal progress dialog
fun showHorizontalProgress(
title: String,
message: String,
max: Int
): AlertDialog {
val builder = AlertDialog.Builder(activity)
val progressBar = android.widget.ProgressBar(activity, null, android.R.attr.progressBarStyleHorizontal)
progressBar.max = max
builder.setTitle(title)
.setView(progressBar)
.setCancelable(false)
val dialog = builder.create()
dialog.show()
return dialog
}
}
// Main demonstration
fun demonstrateMessageBoxes(activity: AppCompatActivity) {
println("=== Android Kotlin Message Box Examples ===\n")
// 1. Alert dialogs
println("--- 1. Alert Dialogs ---")
val alertDialogHelper = AlertDialogHelper(activity)
alertDialogHelper.showAlert("Information", "This is an alert dialog")
alertDialogHelper.showAlertWithCallback("Notice", "Operation completed") {
println("Callback executed")
}
alertDialogHelper.showConfirmDialog(
"Confirm",
"Are you sure you want to continue?",
onConfirm = { println("User confirmed") },
onCancel = { println("User cancelled") }
)
// 2. Input dialogs
println("\n--- 2. Input Dialogs ---")
val inputDialogHelper = InputDialogHelper(activity)
inputDialogHelper.showInputDialog("Enter Name", "Name") { name ->
println("Entered name: $name")
}
inputDialogHelper.showPasswordDialog("Password") { password ->
println("Password entered: ${password.length} chars")
}
// 3. List dialogs
println("\n--- 3. List Dialogs ---")
val listDialogHelper = ListDialogHelper(activity)
val items = listOf("Option 1", "Option 2", "Option 3", "Option 4")
listDialogHelper.showSingleChoiceList("Choose an option", items) { index ->
println("Selected: ${items[index]}")
}
listDialogHelper.showListDialog("Select item", items) { item ->
println("Selected: $item")
}
// 4. Toast messages
println("\n--- 4. Toast Messages ---")
val toastHelper = ToastHelper(activity)
toastHelper.showShort("Short toast message")
toastHelper.showLong("Long toast message")
toastHelper.showWithPosition(
"Positioned toast",
android.view.Gravity.BOTTOM or android.view.Gravity.END,
0,
100
)
// 5. Snackbar
println("\n--- 5. Snackbar ---")
// Note: Snackbar requires a View as anchor
println("Snackbar examples:")
println(" - show(): Simple snackbar")
println(" - showLong(): Long duration snackbar")
println(" - showWithAction(): With action button")
println(" - showIndefinite(): Until dismissed")
println(" - showStyled(): Custom styling")
// 6. Progress dialogs
println("\n--- 6. Progress Dialogs ---")
val progressDialogHelper = ProgressDialogHelper(activity)
val progressDialog = progressDialogHelper.showIndeterminateProgress(
"Loading",
"Please wait..."
)
// Simulate loading
activity.runOnUiThread {
// In real app, dismiss when operation completes
// progressDialog.dismiss()
}
println("\n=== All Message Box Examples Completed ===")
}
💻 Cuadros de Diálogo de Archivos kotlin
🟡 intermediate
⭐⭐⭐⭐
Abrir selector de archivos, cuadro de diálogo guardar y selección de directorio usando Marco de Acceso a Almacenamiento
⏱️ 30 min
🏷️ kotlin, android, ui, dialogs
Prerequisites:
Intermediate Kotlin, Android SDK
// Android Kotlin File Dialog Examples
// Using Storage Access Framework and Intent
import android.app.Activity
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.provider.DocumentsContract
import android.provider.OpenableColumns
import android.content.ContentResolver
import android.database.Cursor
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.fragment.app.Fragment
import androidx.appcompat.app.AppCompatActivity
// 1. Open File Dialog
class OpenFileDialogHelper(private val activity: AppCompatActivity) {
// Create open file launcher
private val openFileLauncher = activity.registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == Activity.RESULT_OK) {
result.data?.data?.also { uri ->
handleFileSelected(uri)
}
}
}
// Open single file
fun openFile(mimeType: String = "*/*") {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = mimeType
putExtra(Intent.EXTRA_TITLE, "Select a file")
}
openFileLauncher.launch(intent)
}
// Open multiple files
private val openMultipleFilesLauncher = activity.registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == Activity.RESULT_OK) {
result.data?.let { intent ->
val clipData = intent.clipData
if (clipData != null) {
for (i in 0 until clipData.itemCount) {
val uri = clipData.getItemAt(i).uri
handleFileSelected(uri)
}
} else {
intent.data?.also { uri ->
handleFileSelected(uri)
}
}
}
}
}
fun openMultipleFiles(mimeType: String = "*/*") {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = mimeType
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
}
openMultipleFilesLauncher.launch(intent)
}
// Open specific file types
fun openImage() {
openFile("image/*")
}
fun openPdf() {
openFile("application/pdf")
}
fun openTextFile() {
openFile("text/*")
}
// Handle selected file
private fun handleFileSelected(uri: Uri) {
val fileName = getFileName(uri)
val fileSize = getFileSize(uri)
println("File selected: $fileName")
println("Size: $fileSize bytes")
println("URI: $uri")
// Read file content
val content = readFileContent(uri)
println("Content preview: ${content?.take(100)}...")
}
// Get file name
private fun getFileName(uri: Uri): String? {
var result: String? = null
if (uri.scheme == "content") {
val cursor: Cursor? = activity.contentResolver.query(
uri,
null,
null,
null,
null
)
cursor?.use {
if (it.moveToFirst()) {
val index = it.getColumnIndex(OpenableColumns.DISPLAY_NAME)
if (index >= 0) {
result = it.getString(index)
}
}
}
}
if (result == null) {
result = uri.path
val cut = result?.lastIndexOf('/')
if (cut != -1) {
result = result?.substring(cut!! + 1)
}
}
return result
}
// Get file size
private fun getFileSize(uri: Uri): Long {
val cursor: Cursor? = activity.contentResolver.query(
uri,
arrayOf(OpenableColumns.SIZE),
null,
null,
null
)
cursor?.use {
if (it.moveToFirst()) {
val sizeIndex = it.getColumnIndex(OpenableColumns.SIZE)
if (sizeIndex >= 0 && !it.isNull(sizeIndex)) {
return it.getLong(sizeIndex)
}
}
}
return 0L
}
// Read file content
private fun readFileContent(uri: Uri): String? {
return try {
activity.contentResolver.openInputStream(uri)?.bufferedReader()?.use { it.readText() }
} catch (e: Exception) {
println("Error reading file: ${e.message}")
null
}
}
}
// 2. Save File Dialog
class SaveFileDialogHelper(private val activity: AppCompatActivity) {
private val saveFileLauncher = activity.registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == Activity.RESULT_OK) {
result.data?.data?.also { uri ->
handleFileSaved(uri)
}
}
}
// Create new file
fun createFile(fileName: String, mimeType: String = "text/plain") {
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = mimeType
putExtra(Intent.EXTRA_TITLE, fileName)
}
saveFileLauncher.launch(intent)
}
// Save text content
fun saveTextFile(fileName: String, content: String) {
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "text/plain"
putExtra(Intent.EXTRA_TITLE, fileName)
}
saveFileLauncher.launch(Intent.createChooser(intent, "Save file"))
}
// Save image
fun saveImageFile(fileName: String) {
createFile(fileName, "image/png")
}
// Handle file saved
private fun handleFileSaved(uri: Uri) {
// Take persistable permission
val takeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
activity.contentResolver.takePersistableUriPermission(uri, takeFlags)
println("File saved: $uri")
// Write content to file
try {
activity.contentResolver.openOutputStream(uri)?.use { outputStream ->
val content = "Sample content written at ${java.util.Date()}"
outputStream.write(content.toByteArray())
}
println("Content written successfully")
} catch (e: Exception) {
println("Error writing file: ${e.message}")
}
}
// Write bytes to file
fun writeToFile(uri: Uri, data: ByteArray): Boolean {
return try {
activity.contentResolver.openOutputStream(uri)?.use { outputStream ->
outputStream.write(data)
outputStream.flush()
}
true
} catch (e: Exception) {
println("Error writing: ${e.message}")
false
}
}
}
// 3. Directory Selection
class DirectoryPickerHelper(private val activity: AppCompatActivity) {
private val directoryPickerLauncher = activity.registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == Activity.RESULT_OK) {
result.data?.data?.also { uri ->
handleDirectorySelected(uri)
}
}
}
// Open directory picker
fun openDirectory() {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
putExtra(DocumentsContract.EXTRA_INITIAL_URI, null)
}
directoryPickerLauncher.launch(intent)
}
// Handle directory selected
private fun handleDirectorySelected(uri: Uri) {
// Take persistable permission
val takeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
activity.contentResolver.takePersistableUriPermission(uri, takeFlags)
println("Directory selected: $uri")
// List files in directory
listFilesInDirectory(uri)
}
// List files in directory
private fun listFilesInDirectory(directoryUri: Uri) {
val childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(
directoryUri,
DocumentsContract.getDocumentId(directoryUri)
)
val cursor: Cursor? = activity.contentResolver.query(
childrenUri,
arrayOf(
DocumentsContract.Document.COLUMN_DISPLAY_NAME,
DocumentsContract.Document.COLUMN_MIME_TYPE
),
null,
null,
null
)
cursor?.use {
println("Files in directory:")
while (it.moveToNext()) {
val nameIndex = it.getColumnIndex(DocumentsContract.Document.COLUMN_DISPLAY_NAME)
val mimeIndex = it.getColumnIndex(DocumentsContract.Document.COLUMN_MIME_TYPE)
val name = it.getString(nameIndex)
val mimeType = it.getString(mimeIndex)
println(" - $name ($mimeType)")
}
}
}
// Create subdirectory
fun createSubdirectory(parentUri: Uri, directoryName: String): Uri? {
return try {
val documentUri = DocumentsContract.createDocument(
activity.contentResolver,
parentUri,
DocumentsContract.Document.MIME_TYPE_DIR,
directoryName
)
documentUri
} catch (e: Exception) {
println("Error creating directory: ${e.message}")
null
}
}
}
// 4. Advanced File Operations
class AdvancedFileOperations(private val activity: AppCompatActivity) {
// Open file with custom filter
fun openWithFilter(mimeTypes: List<String>) {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = if (mimeTypes.size == 1) mimeTypes[0] else "*/*"
if (mimeTypes.size > 1) {
putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes.toTypedArray())
}
}
activity.startActivityForResult(intent, 1001)
}
// Get file metadata
fun getFileMetadata(uri: Uri): FileMetadata? {
val cursor: Cursor? = activity.contentResolver.query(
uri,
arrayOf(
OpenableColumns.DISPLAY_NAME,
OpenableColumns.SIZE,
OpenableColumns.MIME_TYPE
),
null,
null,
null
)
return cursor?.use {
if (it.moveToFirst()) {
val nameIndex = it.getColumnIndex(OpenableColumns.DISPLAY_NAME)
val sizeIndex = it.getColumnIndex(OpenableColumns.SIZE)
val mimeIndex = it.getColumnIndex(OpenableColumns.MIME_TYPE)
FileMetadata(
name = it.getString(nameIndex),
size = it.getLong(sizeIndex),
mimeType = it.getString(mimeIndex)
)
} else {
null
}
}
}
// File metadata data class
data class FileMetadata(
val name: String,
val size: Long,
val mimeType: String
)
}
// 5. Recent Documents
class RecentDocuments(private val activity: AppCompatActivity) {
// Get recent files
fun getRecentDocuments(): List<Uri> {
val recentUris = mutableListOf<Uri>()
// Query recent documents
val projection = arrayOf(
OpenableColumns.DISPLAY_NAME,
OpenableColumns.DATE_MODIFIED
)
val cursor: Cursor? = activity.contentResolver.query(
android.provider.MediaStore.Files.getContentUri("external"),
projection,
null,
null,
"${OpenableColumns.DATE_MODIFIED} DESC LIMIT 10"
)
cursor?.use {
val idIndex = it.getColumnIndex(android.provider.BaseColumns._ID)
while (it.moveToNext()) {
val id = it.getLong(idIndex)
val contentUri = android.provider.MediaStore.Files.getContentUri("external", id)
recentUris.add(contentUri)
}
}
return recentUris
}
}
// Main demonstration
fun demonstrateFileDialogs(activity: AppCompatActivity) {
println("=== Android Kotlin File Dialog Examples ===\n")
// 1. Open file dialog
println("--- 1. Open File Dialog ---")
val openDialogHelper = OpenFileDialogHelper(activity)
println("Opening file dialog...")
openDialogHelper.openFile()
println("\nOpening image picker...")
openDialogHelper.openImage()
println("\nOpening multiple files...")
openDialogHelper.openMultipleFiles()
// 2. Save file dialog
println("\n--- 2. Save File Dialog ---")
val saveDialogHelper = SaveFileDialogHelper(activity)
println("Creating new file...")
saveDialogHelper.createFile("example.txt", "text/plain")
println("\nSaving text file...")
saveDialogHelper.saveTextFile("note.txt", "Sample content")
// 3. Directory picker
println("\n--- 3. Directory Picker ---")
val directoryPicker = DirectoryPickerHelper(activity)
println("Opening directory picker...")
directoryPicker.openDirectory()
// 4. Advanced operations
println("\n--- 4. Advanced Operations ---")
val advancedOps = AdvancedFileOperations(activity)
println("Opening with multiple MIME type filters...")
advancedOps.openWithFilter(listOf("image/*", "video/*", "audio/*"))
// 5. Recent documents
println("\n--- 5. Recent Documents ---")
val recentDocs = RecentDocuments(activity)
println("Getting recent documents...")
val recent = recentDocs.getRecentDocuments()
println("Found ${recent.size} recent documents")
println("\n=== All File Dialog Examples Completed ===")
}
💻 Bandeja del Sistema (Notificaciones) kotlin
🟡 intermediate
⭐⭐⭐⭐
Mostrar notificaciones en la bandeja del sistema/barra de estado con varias opciones
⏱️ 30 min
🏷️ kotlin, android, notifications, ui
Prerequisites:
Intermediate Kotlin, Android SDK
// Android Kotlin Notification Examples
// Using NotificationManager and NotificationCompat
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import android.graphics.BitmapFactory
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
// 1. Basic Notification
class BasicNotificationHelper(private val context: Context) {
companion object {
private const val CHANNEL_ID = "basic_channel"
private const val NOTIFICATION_ID = 1001
}
private val notificationManager = NotificationManagerCompat.from(context)
init {
createNotificationChannel()
}
// Create notification channel (required for Android O+)
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
CHANNEL_ID,
"Basic Notifications",
NotificationManager.IMPORTANCE_DEFAULT
).apply {
description = "Basic notification channel"
enableLights(true)
lightColor = Color.BLUE
}
val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
manager.createNotificationChannel(channel)
}
}
// Show simple notification
fun showNotification(title: String, message: String) {
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle(title)
.setContentText(message)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setAutoCancel(true)
notificationManager.notify(NOTIFICATION_ID, builder.build())
}
// Show notification with large text
fun showNotificationWithLargeText(title: String, message: String) {
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle(title)
.setContentText(message)
.setStyle(
NotificationCompat.BigTextStyle()
.bigText(message)
)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setAutoCancel(true)
notificationManager.notify(NOTIFICATION_ID, builder.build())
}
}
// 2. Notification with Actions
class ActionNotificationHelper(private val context: Context) {
companion object {
private const val CHANNEL_ID = "action_channel"
private const val NOTIFICATION_ID = 1002
}
private val notificationManager = NotificationManagerCompat.from(context)
init {
createNotificationChannel()
}
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
CHANNEL_ID,
"Action Notifications",
NotificationManager.IMPORTANCE_HIGH
).apply {
description = "Notifications with action buttons"
}
val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
manager.createNotificationChannel(channel)
}
}
// Notification with action button
fun showNotificationWithAction(
title: String,
message: String,
actionText: String,
actionIntent: PendingIntent
) {
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle(title)
.setContentText(message)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.addAction(
android.R.drawable.ic_menu_send,
actionText,
actionIntent
)
.setAutoCancel(true)
notificationManager.notify(NOTIFICATION_ID, builder.build())
}
// Multiple actions
fun showNotificationWithMultipleActions(
title: String,
message: String,
actions: List<NotificationAction>
) {
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle(title)
.setContentText(message)
.setPriority(NotificationCompat.PRIORITY_HIGH)
actions.forEach { action ->
builder.addAction(action.icon, action.title, action.pendingIntent)
}
builder.setAutoCancel(true)
notificationManager.notify(NOTIFICATION_ID, builder.build())
}
// Data class for notification action
data class NotificationAction(
val icon: Int,
val title: String,
val pendingIntent: PendingIntent
)
}
// 3. Progress Notification
class ProgressNotificationHelper(private val context: Context) {
companion object {
private const val CHANNEL_ID = "progress_channel"
private const val NOTIFICATION_ID = 1003
}
private val notificationManager = NotificationManagerCompat.from(context)
init {
createNotificationChannel()
}
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
CHANNEL_ID,
"Progress Notifications",
NotificationManager.IMPORTANCE_LOW
)
val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
manager.createNotificationChannel(channel)
}
}
// Show indeterminate progress
fun showIndeterminateProgress(title: String, message: String) {
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle(title)
.setContentText(message)
.setPriority(NotificationCompat.PRIORITY_LOW)
.setOngoing(true)
.setProgress(0, 0, true)
notificationManager.notify(NOTIFICATION_ID, builder.build())
}
// Show determinate progress
fun showProgress(title: String, message: String, max: Int, progress: Int) {
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle(title)
.setContentText(message)
.setPriority(NotificationCompat.PRIORITY_LOW)
.setOngoing(true)
.setProgress(max, progress, false)
notificationManager.notify(NOTIFICATION_ID, builder.build())
}
// Update progress
fun updateProgress(max: Int, progress: Int, message: String? = null) {
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle("Downloading")
.setContentText(message ?: "$progress%")
.setOngoing(true)
.setProgress(max, progress, false)
notificationManager.notify(NOTIFICATION_ID, builder.build())
}
// Complete progress
fun completeProgress(title: String, message: String) {
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle(title)
.setContentText(message)
.setProgress(0, 0, false)
.setOngoing(false)
.setAutoCancel(true)
notificationManager.notify(NOTIFICATION_ID, builder.build())
}
}
// 4. Rich Notification with Image
class RichNotificationHelper(private val context: Context) {
companion object {
private const val CHANNEL_ID = "rich_channel"
private const val NOTIFICATION_ID = 1004
}
private val notificationManager = NotificationManagerCompat.from(context)
init {
createNotificationChannel()
}
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
CHANNEL_ID,
"Rich Notifications",
NotificationManager.IMPORTANCE_HIGH
).apply {
description = "Rich notifications with images"
}
val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
manager.createNotificationChannel(channel)
}
}
// Big picture notification
fun showBigPictureNotification(
title: String,
message: String,
imageBitmap: android.graphics.Bitmap
) {
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle(title)
.setContentText(message)
.setLargeIcon(imageBitmap)
.setStyle(
NotificationCompat.BigPictureStyle()
.bigPicture(imageBitmap)
.bigLargeIcon(null)
)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
notificationManager.notify(NOTIFICATION_ID, builder.build())
}
// Inbox style notification
fun showInboxNotification(
title: String,
contentTitle: String,
lines: List<String>
) {
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle(title)
.setContentText(contentTitle)
.setStyle(
NotificationCompat.InboxStyle()
.setSummaryText("${lines.size} new messages")
.addLine(lines[0])
)
.setPriority(NotificationCompat.PRIORITY_HIGH)
// Add remaining lines
for (i in 1 until minOf(lines.size, 5)) {
builder.setStyle(
NotificationCompat.InboxStyle()
.setSummaryText("${lines.size} new messages")
.addLine(lines[i])
)
}
builder.setAutoCancel(true)
notificationManager.notify(NOTIFICATION_ID, builder.build())
}
}
// 5. Notification Groups
class GroupNotificationHelper(private val context: Context) {
companion object {
private const val CHANNEL_ID = "group_channel"
private const val GROUP_ID = "notification_group"
private const val SUMMARY_ID = 1005
}
private val notificationManager = NotificationManagerCompat.from(context)
init {
createNotificationChannel()
}
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
CHANNEL_ID,
"Group Notifications",
NotificationManager.IMPORTANCE_HIGH
)
val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
manager.createNotificationChannel(channel)
}
}
// Show grouped notifications
fun showGroupedNotifications(
notifications: List<GroupedNotification>
) {
// Show individual notifications
notifications.forEach { notification ->
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle(notification.title)
.setContentText(notification.message)
.setGroup(GROUP_ID)
.setAutoCancel(true)
notificationManager.notify(notification.id, builder.build())
}
// Show summary notification
val summaryBuilder = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle("Group Summary")
.setContentText("${notifications.size} notifications")
.setGroup(GROUP_ID)
.setGroupSummary(true)
.setAutoCancel(true)
notificationManager.notify(SUMMARY_ID, summaryBuilder.build())
}
// Data class for grouped notification
data class GroupedNotification(
val id: Int,
val title: String,
val message: String
)
}
// 6. Notification Manager
class UnifiedNotificationManager(private val context: Context) {
private val basicHelper = BasicNotificationHelper(context)
private val actionHelper = ActionNotificationHelper(context)
private val progressHelper = ProgressNotificationHelper(context)
private val richHelper = RichNotificationHelper(context)
private val groupHelper = GroupNotificationHelper(context)
// Show simple notification
fun notify(title: String, message: String) {
basicHelper.showNotification(title, message)
}
// Show notification with action
fun notifyWithAction(
title: String,
message: String,
actionText: String,
actionIntent: PendingIntent
) {
actionHelper.showNotificationWithAction(title, message, actionText, actionIntent)
}
// Show progress
fun showProgress(title: String, message: String, max: Int, progress: Int) {
progressHelper.showProgress(title, message, max, progress)
}
// Cancel all notifications
fun cancelAll() {
val manager = NotificationManagerCompat.from(context)
manager.cancelAll()
}
// Cancel specific notification
fun cancel(id: Int) {
val manager = NotificationManagerCompat.from(context)
manager.cancel(id)
}
}
// Main demonstration
fun demonstrateSystemTray(context: Context, activity: AppCompatActivity) {
println("=== Android Kotlin Notification Examples ===\n")
// 1. Basic notifications
println("--- 1. Basic Notifications ---")
val basicHelper = BasicNotificationHelper(context)
basicHelper.showNotification(
"Basic Notification",
"This is a simple notification"
)
basicHelper.showNotificationWithLargeText(
"Long Notification",
"This is a notification with a very long message that " +
"should be displayed using the big text style in the notification drawer."
)
// 2. Action notifications
println("\n--- 2. Action Notifications ---")
val actionHelper = ActionNotificationHelper(context)
// Create pending intent
val intent = Intent(context, activity::class.java)
val pendingIntent = PendingIntent.getActivity(
context,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
actionHelper.showNotificationWithAction(
"Action Notification",
"Click to perform action",
"Reply",
pendingIntent
)
// 3. Progress notifications
println("\n--- 3. Progress Notifications ---")
val progressHelper = ProgressNotificationHelper(context)
progressHelper.showIndeterminateProgress("Indeterminate", "Working...")
// Simulate progress
val max = 100
for (i in 0..100 step 10) {
progressHelper.updateProgress(max, i, "Download: $i%")
}
progressHelper.completeProgress("Complete", "Download finished!")
// 4. Rich notifications
println("\n--- 4. Rich Notifications ---")
val richHelper = RichNotificationHelper(context)
// Note: In real usage, you'd have actual bitmap
println("Rich notification types:")
println(" - Big picture style")
println(" - Inbox style")
println(" - Messaging style")
// 5. Group notifications
println("\n--- 5. Group Notifications ---")
val groupHelper = GroupNotificationHelper(context)
val notifications = listOf(
GroupNotificationHelper.GroupedNotification(
1,
"Message 1",
"First message"
),
GroupNotificationHelper.GroupedNotification(
2,
"Message 2",
"Second message"
),
GroupNotificationHelper.GroupedNotification(
3,
"Message 3",
"Third message"
)
)
groupHelper.showGroupedNotifications(notifications)
// 6. Unified manager
println("\n--- 6. Unified Notification Manager ---")
val unifiedManager = UnifiedNotificationManager(context)
println("Unified manager provides:")
println(" - notify(): Simple notifications")
println(" - notifyWithAction(): With action buttons")
println(" - showProgress(): Progress notifications")
println(" - cancelAll(): Cancel all notifications")
println("\n=== All Notification Examples Completed ===")
}