Introducción: ¿por qué invocar una Activity desde otra aplicación?
\n\nImagine que está creando una aplicación de notas y desea permitir al usuario tomar una foto directamente desde su interfaz. O, supongamos que su mensajero debe abrir los contactos de la libreta de direcciones. En ambos casos, necesita iniciar una Activity desde otra aplicación en Android.
\n\nEsta tarea es una de las preguntas más populares en Stack Overflow (miles de visitas y cientos de votos). Y con razón: si se hace incorrectamente, la aplicación puede fallar con ActivityNotFoundException o, peor aún, crear un riesgo de seguridad. En este tutorial, analizaremos todos los detalles en el lenguaje Kotlin para que pueda integrar con confianza pantallas externas en sus proyectos.
Por cierto, está en el sitio PythonLib, donde a menudo hablamos de Python, pero hoy es un caso especial. El desarrollo de Android con Kotlin es una habilidad poderosa que se combina perfectamente con un backend en Python. ¡Vamos allá!
\n\n¿Qué es un Intent y por qué es la clave de la solución?
\n\nEn Android, un Intent es un mensaje que le dice al sistema: «Oye, necesito hacer algo con tal acción». Para iniciar una Activity desde otra aplicación se utilizan dos enfoques:
\n\n- \n
- Intent explícito — sabe exactamente qué componente desea iniciar (por ejemplo,
com.example.target.MainActivity). Solo funciona si tiene acceso al código de esa aplicación. \n - Intent implícito — describe lo que quiere hacer (por ejemplo, «abrir un mapa con coordenadas»), y el sistema mismo encuentra la aplicación adecuada. Esta es una forma más flexible y segura para invocar una Activity externa. \n
Nos centraremos en los Intent implícitos, ya que son los más utilizados para la comunicación entre procesos en Android.
\n\nEjemplo básico: abrir un mapa con coordenadas
\n\nEmpecemos con un ejemplo simple que muestra cómo iniciar una Activity desde otra aplicación para mostrar un mapa.
\n\n// Kotlin\nval gmmIntentUri = Uri.parse("geo:55.7558,37.6173?z=15")\nval mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)\nmapIntent.setPackage("com.google.android.apps.maps")\n\n// Verificamos si hay una aplicación que pueda procesar el Intent\nif (mapIntent.resolveActivity(packageManager) != null) {\n startActivity(mapIntent)\n} else {\n // Mostramos un mensaje de error al usuario\n Toast.makeText(this, "Google Maps no está instalado", Toast.LENGTH_SHORT).show()\n}\n\n¿Qué sucede aquí? Creamos un Intent con la acción ACTION_VIEW y un URI que contiene las coordenadas. Luego, con setPackage indicamos explícitamente que queremos usar Google Maps (aunque esto es opcional — el sistema puede ofrecer una selección). Lo más importante es la verificación mediante resolveActivity. Esto evita un bloqueo si la aplicación necesaria no está presente en el dispositivo.
Escenario: invocar la cámara y obtener un resultado
\n\nAhora pasemos a un caso más complejo: iniciar una Activity desde otra aplicación esperando un resultado. El ejemplo clásico: tomar una foto y recibirla en su aplicación.
\n\n// Kotlin\nprivate const val REQUEST_IMAGE_CAPTURE = 1\n\nprivate fun dispatchTakePictureIntent() {\n val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)\n // Verificamos que la cámara esté disponible\n if (takePictureIntent.resolveActivity(packageManager) != null) {\n startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)\n } else {\n // Manejo de error: cámara no encontrada\n }\n}\n\noverride fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {\n super.onActivityResult(requestCode, resultCode, data)\n if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == Activity.RESULT_OK) {\n val imageBitmap = data?